@api.global/typedserver
Version:
A TypeScript-based project for easy serving of static files with support for live reloading, compression, and typed requests.
150 lines • 13.8 kB
JavaScript
import * as plugins from '../plugins.js';
import * as interfaces from '../../dist_ts_interfaces/index.js';
import { Handler } from './classes.handler.js';
import { Compressor } from './classes.compressor.js';
export class HandlerStatic extends Handler {
compressor = new Compressor();
constructor(pathArg, optionsArg) {
super('GET', async (req, res) => {
let requestPath = req.path;
let requestHeaders = req.headers;
let requestBody = req.body;
let travelData;
if (optionsArg && optionsArg.requestModifier) {
const modifiedRequest = await optionsArg.requestModifier({
headers: requestHeaders,
path: requestPath,
body: requestBody,
});
requestHeaders = modifiedRequest.headers;
requestPath = modifiedRequest.path;
requestBody = modifiedRequest.body;
travelData = modifiedRequest.travelData;
}
// lets compute some paths
// Extract the path using Express 5's params or fallback methods
let filePath;
if (req.params && req.params.splat !== undefined) {
// Express 5 wildcard route (/*splat or /{*splat})
// Handle array values - join them if array, otherwise use as-is
filePath = Array.isArray(req.params.splat) ? req.params.splat.join('/') : String(req.params.splat || '');
}
else if (req.params && req.params[0] !== undefined) {
// Numbered parameter fallback
filePath = Array.isArray(req.params[0]) ? req.params[0].join('/') : String(req.params[0] || '');
}
else if (req.baseUrl) {
// If there's a baseUrl, remove it from the path
filePath = requestPath.slice(req.baseUrl.length);
}
else if (req.route && req.route.path === '/') {
// Root route - use full path minus leading slash
filePath = requestPath.slice(1);
}
else {
// Fallback to the original slicing logic for compatibility
filePath = requestPath.slice(req.route.path.length - 1);
}
// Ensure filePath is a string and has no leading slash
filePath = String(filePath || '');
if (filePath.startsWith('/')) {
filePath = filePath.slice(1);
}
if (requestPath === '') {
console.log('replaced root with index.html');
filePath = 'index.html';
}
console.log(filePath);
const joinedPath = plugins.path.join(pathArg, filePath);
const defaultPath = plugins.path.join(pathArg, 'index.html');
let parsedPath = plugins.path.parse(joinedPath);
let usedPath;
// important security checks
if (requestPath.includes('..') || // don't allow going up the filePath
requestPath.includes('~') || // don't allow referencing of home directory
!joinedPath.startsWith(pathArg) // make sure the joined path is within the directory
) {
res.writeHead(500);
res.end();
return;
}
// set additional headers
if (optionsArg && optionsArg.headers) {
for (const key of Object.keys(optionsArg.headers)) {
res.set(key, optionsArg.headers[key]);
}
}
// lets actually care about serving, if security checks pass
let fileBuffer;
try {
fileBuffer = await plugins.fsInstance.file(joinedPath).read();
usedPath = joinedPath;
}
catch (err) {
// try serving index.html instead
console.log(`could not resolve ${joinedPath}`);
if (optionsArg && optionsArg.serveIndexHtmlDefault) {
console.log(`serving default path ${defaultPath} instead of ${joinedPath}`);
try {
parsedPath = plugins.path.parse(defaultPath);
fileBuffer = await plugins.fsInstance.file(defaultPath).read();
usedPath = defaultPath;
}
catch (err) {
res.writeHead(500);
res.end('File not found!');
return;
}
}
else {
res.writeHead(500);
res.end('File not found!');
return;
}
}
res.type(parsedPath.ext);
const headers = res.getHeaders();
// lets modify the response at last
if (optionsArg && optionsArg.responseModifier) {
const modifiedResponse = await optionsArg.responseModifier({
headers: res.getHeaders(),
path: usedPath,
responseContent: fileBuffer,
travelData,
});
// headers
for (const key of Object.keys(res.getHeaders())) {
if (!modifiedResponse.headers[key]) {
res.removeHeader(key);
}
}
for (const key of Object.keys(modifiedResponse.headers)) {
res.setHeader(key, modifiedResponse.headers[key]);
}
// responseContent
fileBuffer = modifiedResponse.responseContent;
}
// lets finally deal with compression
let compressionResult;
if (optionsArg && optionsArg.enableCompression) {
compressionResult = await this.compressor.maybeCompress(requestHeaders, fileBuffer, [optionsArg.preferredCompressionMethod]);
}
else {
compressionResult = {
compressionMethod: 'none',
result: fileBuffer,
};
}
res.status(200);
if (compressionResult?.compressionMethod) {
res.header('Content-Encoding', compressionResult.compressionMethod);
res.write(compressionResult.result);
}
else {
res.write(fileBuffer);
}
res.end();
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5oYW5kbGVyc3RhdGljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc2VydmVydG9vbHMvY2xhc3Nlcy5oYW5kbGVyc3RhdGljLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sbUNBQW1DLENBQUM7QUFFaEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQW9ELE1BQU0seUJBQXlCLENBQUM7QUFFdkcsTUFBTSxPQUFPLGFBQWMsU0FBUSxPQUFPO0lBQ2pDLFVBQVUsR0FBRyxJQUFJLFVBQVUsRUFBRSxDQUFDO0lBQ3JDLFlBQ0UsT0FBZSxFQUNmLFVBT0M7UUFFRCxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDOUIsSUFBSSxXQUFXLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztZQUMzQixJQUFJLGNBQWMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDO1lBQ2pDLElBQUksV0FBVyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7WUFDM0IsSUFBSSxVQUFtQixDQUFDO1lBQ3hCLElBQUksVUFBVSxJQUFJLFVBQVUsQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDN0MsTUFBTSxlQUFlLEdBQUcsTUFBTSxVQUFVLENBQUMsZUFBZSxDQUFDO29CQUN2RCxPQUFPLEVBQUUsY0FBYztvQkFDdkIsSUFBSSxFQUFFLFdBQVc7b0JBQ2pCLElBQUksRUFBRSxXQUFXO2lCQUNsQixDQUFDLENBQUM7Z0JBRUgsY0FBYyxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUM7Z0JBQ3pDLFdBQVcsR0FBRyxlQUFlLENBQUMsSUFBSSxDQUFDO2dCQUNuQyxXQUFXLEdBQUcsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDbkMsVUFB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