feat(typedserver): Add configurable security headers and default SPA behavior

Introduce structured security headers support (CSP, HSTS, X-Frame-Options, COOP/COEP/CORP, Permissions-Policy, Referrer-Policy, X-XSS-Protection, etc.) and apply them to responses and OPTIONS preflight. Expose configuration via the server API and document usage. Also update UtilityWebsiteServer defaults (SPA fallback enabled by default) and related docs.
This commit is contained in:
2025-12-05 13:13:59 +00:00
parent 2f064c7ea8
commit ffb00cdb71
5 changed files with 367 additions and 28 deletions

View File

@@ -1,13 +1,28 @@
import * as interfaces from '../../dist_ts_interfaces/index.js';
import { type IServerOptions, TypedServer } from '../classes.typedserver.js';
import { type IServerOptions, type ISecurityHeaders, TypedServer } from '../classes.typedserver.js';
import * as plugins from '../plugins.js';
export interface IUtilityWebsiteServerConstructorOptions {
/** Custom route handler to add additional routes */
addCustomRoutes?: (typedserver: TypedServer) => Promise<any>;
/** Application semantic version */
appSemVer?: string;
/** Domain name for the website */
domain: string;
/** Directory to serve static files from */
serveDir: string;
feedMetadata: IServerOptions['feedMetadata'];
/** RSS feed metadata */
feedMetadata?: IServerOptions['feedMetadata'];
/** Enable/disable CORS (default: true) */
cors?: boolean;
/** Enable/disable SPA fallback (default: true) */
spaFallback?: boolean;
/** Security headers configuration */
securityHeaders?: ISecurityHeaders;
/** Force SSL redirect (default: false) */
forceSsl?: boolean;
/** Port to listen on (default: 3000) */
port?: number;
}
/**
@@ -29,14 +44,28 @@ export class UtilityWebsiteServer {
/**
* Start the website server
*/
public async start(portArg = 3000) {
public async start(portArg?: number) {
const port = portArg ?? this.options.port ?? 3000;
this.typedserver = new TypedServer({
cors: true,
injectReload: true,
watch: true,
// Core settings
cors: this.options.cors ?? true,
serveDir: this.options.serveDir,
domain: this.options.domain,
forceSsl: false,
port,
// Development features
injectReload: true,
watch: true,
// SPA support (enabled by default for modern web apps)
spaFallback: this.options.spaFallback ?? true,
// Security
forceSsl: this.options.forceSsl ?? false,
securityHeaders: this.options.securityHeaders,
// PWA manifest
manifest: {
name: this.options.domain,
short_name: this.options.domain,
@@ -46,11 +75,11 @@ export class UtilityWebsiteServer {
background_color: '#000000',
scope: '/',
},
port: portArg,
// features
// SEO features
robots: true,
sitemap: true,
feedMetadata: this.options.feedMetadata,
});
let lswData: interfaces.serviceworker.IRequest_Serviceworker_Backend_VersionInfo['response'] = {