@intuitionrobotics/thunderstorm
Version:
109 lines • 3.95 kB
JavaScript
import compression from 'compression';
import cors from 'cors';
import { addItemToArray, LogLevel, Module } from "@intuitionrobotics/ts-common";
import { ServerApi } from "./server-api.js";
import { ApiException } from "../../exceptions.js";
import express from "express";
import { HeaderKey_FunctionExecutionId, HeaderKey_JWT } from '../_imports.js';
const DefaultHeaders = [
'content-type',
'content-encoding',
'x-session-id',
'authorization'
];
const ExposedHeaders = [
HeaderKey_FunctionExecutionId,
HeaderKey_JWT
];
export class HttpServer_Class extends Module {
static expressMiddleware = [];
express;
constructor(_express, configElement) {
super("HttpServer");
this.express = _express;
this.setConfig(configElement);
}
static addMiddleware(middleware) {
HttpServer_Class.expressMiddleware.push(middleware);
return this;
}
getBaseUrl() {
return this.config.baseUrl;
}
init() {
this.setMinLevel(ServerApi.isDebug ? LogLevel.Verbose : LogLevel.Info);
const baseUrl = this.config.baseUrl;
if (baseUrl) {
if (baseUrl.endsWith("/"))
this.config.baseUrl = baseUrl.substring(0, baseUrl.length - 1);
this.config.baseUrl = baseUrl.replace(/\/\//g, "/");
}
this.express.use((req, res, next) => {
if (req)
req.url = req.url.replace(/\/\//g, "/");
next();
});
const parserLimit = this.config.bodyParserLimit;
if (parserLimit)
this.express.use(express.json({ limit: parserLimit }));
this.express.use(compression());
const myCors = this.config.cors || {};
if (!myCors.exposedHeaders)
myCors.exposedHeaders = ExposedHeaders;
myCors.headers = DefaultHeaders.reduce((toRet, item) => {
if (!toRet.includes(item))
addItemToArray(toRet, item);
return toRet;
}, myCors.headers || []);
const corsOptions = {
credentials: true, // Allow cookies/auth headers
optionsSuccessStatus: 200,
exposedHeaders: myCors.exposedHeaders
};
// Handle origin configuration
if (!myCors.origins || myCors.origins.length === 0) {
// No origins specified - allow all
corsOptions.origin = true;
}
else {
// Single origin string or RegExp
corsOptions.origin = myCors.origins;
}
const corsWithOptions = cors(corsOptions);
this.express.use(corsWithOptions);
for (const middleware of HttpServer_Class.expressMiddleware) {
this.express.use(middleware);
}
this.express.options('*', corsWithOptions);
}
// v2.0 entrypoint: mount a user-built Express Router directly onto the
// app. The hand-maintained routes.ts file constructs the Router using
// the `mount()` helper and `Router.use(...)` for nesting, then this
// method just `app.use`s it. No RouteResolver, no fs walk, no codegen
// walker — Express owns the route table.
//
// `urlPrefix` is optional and matches what `Storm.setInitialRoutePath`
// gave callers: a local-dev URL prefix (e.g. "/api"). When empty, the
// router mounts at the application root.
mountRouter(router, urlPrefix = "") {
if (urlPrefix)
this.express.use(urlPrefix, router);
else
this.express.use(router);
}
}
export class HeaderKey {
key;
responseCode;
constructor(key, responseCode = 400) {
this.key = key;
this.responseCode = responseCode;
}
get(request) {
const value = request.header(this.key);
if (!value)
throw new ApiException(this.responseCode, `Missing expected header: ${this.key}`);
return value;
}
}
//# sourceMappingURL=HttpServer.js.map