80 lines
1.8 KiB
JavaScript
80 lines
1.8 KiB
JavaScript
'use strict';
|
|
|
|
const http = require('http');
|
|
|
|
const PORT = Number(process.env.PORT) || 3000;
|
|
const VM_DOCS_BASE_URL = (process.env.VM_DOCS_BASE_URL || '').replace(/\/+$/, '');
|
|
|
|
const STAND_RE = /^[A-Za-z0-9._-]+$/;
|
|
|
|
function send(res, status, body, headers = {}) {
|
|
const data = Buffer.from(String(body));
|
|
res.writeHead(status, {
|
|
'Content-Type': 'text/plain; charset=utf-8',
|
|
'Content-Length': data.length,
|
|
...headers,
|
|
});
|
|
res.end(data);
|
|
}
|
|
|
|
function redirect(res, location) {
|
|
send(res, 302, '', { Location: location });
|
|
}
|
|
|
|
const server = http.createServer((req, res) => {
|
|
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
send(res, 405, 'Method Not Allowed');
|
|
return;
|
|
}
|
|
|
|
let pathname;
|
|
try {
|
|
pathname = decodeURIComponent(req.url.split('?')[0]);
|
|
} catch (err) {
|
|
send(res, 400, 'Bad Request');
|
|
return;
|
|
}
|
|
|
|
if (pathname === '/health') {
|
|
send(res, 200, 'ok');
|
|
return;
|
|
}
|
|
|
|
if (pathname === '/') {
|
|
if (!VM_DOCS_BASE_URL) {
|
|
send(res, 500, 'VM_DOCS_BASE_URL is not configured');
|
|
return;
|
|
}
|
|
redirect(res, VM_DOCS_BASE_URL + '/');
|
|
return;
|
|
}
|
|
|
|
if (!VM_DOCS_BASE_URL) {
|
|
send(res, 500, 'VM_DOCS_BASE_URL is not configured');
|
|
return;
|
|
}
|
|
|
|
const segments = pathname.split('/').filter((s) => s !== '');
|
|
if (segments.some((s) => s === '..')) {
|
|
send(res, 400, 'Bad Request');
|
|
return;
|
|
}
|
|
|
|
const stand = segments[0];
|
|
if (!stand || !STAND_RE.test(stand)) {
|
|
send(res, 404, 'Not Found');
|
|
return;
|
|
}
|
|
|
|
redirect(res, VM_DOCS_BASE_URL + pathname);
|
|
});
|
|
|
|
if (require.main === module) {
|
|
server.listen(PORT, () => {
|
|
console.log(`redirect router listening on :${PORT}`);
|
|
console.log(`VM_DOCS_BASE_URL=${VM_DOCS_BASE_URL || '(not set)'}`);
|
|
});
|
|
}
|
|
|
|
module.exports = { server, send, redirect };
|