feat: drop /docs URL prefix (variant B, shorter URLs) + bump 0.0.2
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tf-docs",
|
"name": "tf-docs",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"description": "Terraform docs service (S3 static /docs) — initial skeleton",
|
"description": "Terraform docs service (S3 static /docs) — initial skeleton",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const path = require('path');
|
|||||||
const { S3Client, GetObjectCommand, HeadBucketCommand } = require('@aws-sdk/client-s3');
|
const { S3Client, GetObjectCommand, HeadBucketCommand } = require('@aws-sdk/client-s3');
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
const VERSION = process.env.APP_VERSION || '0.0.1';
|
const VERSION = process.env.APP_VERSION || '0.0.2';
|
||||||
const SERVICE = 'tf-docs';
|
const SERVICE = 'tf-docs';
|
||||||
const S3_BUCKET = process.env.S3_BUCKET || '';
|
const S3_BUCKET = process.env.S3_BUCKET || '';
|
||||||
const DOCS_S3_PREFIX = (process.env.DOCS_S3_PREFIX || 'docs').replace(/^\/+|\/+$/g, '');
|
const DOCS_S3_PREFIX = (process.env.DOCS_S3_PREFIX || 'docs').replace(/^\/+|\/+$/g, '');
|
||||||
@@ -22,7 +22,7 @@ const s3 = new S3Client({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function getDocsCandidates(urlPath) {
|
function getDocsCandidates(urlPath) {
|
||||||
const relativePath = decodeURIComponent(urlPath.replace(/^\/docs\/?/, ''));
|
const relativePath = decodeURIComponent(urlPath.replace(/^\/+/, ''));
|
||||||
const normalized = path.posix.normalize(`/${relativePath}`).replace(/^\/+|\/+$/g, '');
|
const normalized = path.posix.normalize(`/${relativePath}`).replace(/^\/+|\/+$/g, '');
|
||||||
if (!normalized || normalized === '.' || normalized.startsWith('../') || normalized.includes('/../')) {
|
if (!normalized || normalized === '.' || normalized.startsWith('../') || normalized.includes('/../')) {
|
||||||
return null;
|
return null;
|
||||||
@@ -106,23 +106,7 @@ const server = http.createServer((req, res) => {
|
|||||||
health(req, res);
|
health(req, res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (req.url.startsWith('/docs/')) {
|
docsHandler(req, res);
|
||||||
docsHandler(req, res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res.statusCode = 200;
|
|
||||||
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
||||||
res.end(`<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>${SERVICE}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>${SERVICE}</h1>
|
|
||||||
<p>version: ${VERSION}</p>
|
|
||||||
</body>
|
|
||||||
</html>`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
|
|||||||
+5
-5
@@ -22,21 +22,21 @@ async function withServer(fn) {
|
|||||||
|
|
||||||
test('candidates: trailing slash -> index.html', () => {
|
test('candidates: trailing slash -> index.html', () => {
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
getDocsCandidates('/docs/nubes/nubes/1.0.0/'),
|
getDocsCandidates('/nubes/nubes/1.0.0/'),
|
||||||
['docs/nubes/nubes/1.0.0/index.html']
|
['docs/nubes/nubes/1.0.0/index.html']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('candidates: file with extension -> exact + root index fallback', () => {
|
test('candidates: file with extension -> exact + root index fallback', () => {
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
getDocsCandidates('/docs/nubes/nubes/1.0.0/page.html'),
|
getDocsCandidates('/nubes/nubes/1.0.0/page.html'),
|
||||||
['docs/nubes/nubes/1.0.0/page.html', 'docs/nubes/nubes/1.0.0/index.html']
|
['docs/nubes/nubes/1.0.0/page.html', 'docs/nubes/nubes/1.0.0/index.html']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('candidates: directory-style path -> exact + index.html + root index', () => {
|
test('candidates: directory-style path -> exact + index.html + root index', () => {
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
getDocsCandidates('/docs/nubes/nubes/1.0.0/guides/getting-started'),
|
getDocsCandidates('/nubes/nubes/1.0.0/guides/getting-started'),
|
||||||
[
|
[
|
||||||
'docs/nubes/nubes/1.0.0/guides/getting-started',
|
'docs/nubes/nubes/1.0.0/guides/getting-started',
|
||||||
'docs/nubes/nubes/1.0.0/guides/getting-started/index.html',
|
'docs/nubes/nubes/1.0.0/guides/getting-started/index.html',
|
||||||
@@ -91,7 +91,7 @@ test('GET /docs/... -> 200 streams body with content-type', async () => {
|
|||||||
return { $metadata: { httpStatusCode: 200 } };
|
return { $metadata: { httpStatusCode: 200 } };
|
||||||
};
|
};
|
||||||
await withServer(async (base) => {
|
await withServer(async (base) => {
|
||||||
const res = await fetch(`${base}/docs/nubes/nubes/1.0.0/`);
|
const res = await fetch(`${base}/nubes/nubes/1.0.0/`);
|
||||||
assert.strictEqual(res.status, 200);
|
assert.strictEqual(res.status, 200);
|
||||||
assert.match(res.headers.get('content-type') || '', /text\/html/);
|
assert.match(res.headers.get('content-type') || '', /text\/html/);
|
||||||
assert.strictEqual(await res.text(), '<html>ok</html>');
|
assert.strictEqual(await res.text(), '<html>ok</html>');
|
||||||
@@ -110,7 +110,7 @@ test('GET /docs/... -> 404 when no key found', async () => {
|
|||||||
return { $metadata: { httpStatusCode: 200 } };
|
return { $metadata: { httpStatusCode: 200 } };
|
||||||
};
|
};
|
||||||
await withServer(async (base) => {
|
await withServer(async (base) => {
|
||||||
const res = await fetch(`${base}/docs/nubes/nubes/1.0.0/missing`);
|
const res = await fetch(`${base}/nubes/nubes/1.0.0/missing`);
|
||||||
assert.strictEqual(res.status, 404);
|
assert.strictEqual(res.status, 404);
|
||||||
});
|
});
|
||||||
s3.send = originalSend;
|
s3.send = originalSend;
|
||||||
|
|||||||
Reference in New Issue
Block a user