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

119
readme.md
View File

@@ -9,12 +9,13 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
## ✨ Features
- 🔒 **Type-Safe API** - Full TypeScript support with `@api.global/typedrequest` and `@api.global/typedsocket`
- 🛡️ **Security Headers** - Built-in CSP, HSTS, X-Frame-Options, and more
-**Live Reload** - Automatic browser refresh on file changes during development
- 🛠️ **Service Worker** - Advanced caching, offline support, and background sync
- ☁️ **Edge Workers** - Cloudflare Workers compatible edge computing with domain routing
- 📡 **WebSocket** - Real-time bidirectional communication via TypedSocket
- 🗺️ **SEO Tools** - Built-in sitemap, RSS feed, and robots.txt generation
- 🎯 **SPA Support** - Single-page application fallback routing
- 🎯 **SPA Support** - Single-page application fallback routing (default in UtilityWebsiteServer)
- 📱 **PWA Ready** - Web App Manifest generation for progressive web apps
## 📦 Installation
@@ -189,6 +190,73 @@ const swClient = await getServiceworkerClient({
// - Background sync
```
## 🛡️ Security Headers
Configure comprehensive security headers including CSP, HSTS, and more:
```typescript
import { TypedServer } from '@api.global/typedserver';
const server = new TypedServer({
serveDir: './dist',
cors: true,
securityHeaders: {
// Content Security Policy
csp: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", 'https://cdn.example.com'],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'", 'wss:', 'https://api.example.com'],
fontSrc: ["'self'", 'https://fonts.gstatic.com'],
frameAncestors: ["'none'"],
upgradeInsecureRequests: true,
},
// HSTS (HTTP Strict Transport Security)
hstsMaxAge: 31536000, // 1 year
hstsIncludeSubDomains: true,
hstsPreload: true,
// Other security headers
xFrameOptions: 'DENY',
xContentTypeOptions: true,
xXssProtection: true,
referrerPolicy: 'strict-origin-when-cross-origin',
// Cross-Origin policies
crossOriginOpenerPolicy: 'same-origin',
crossOriginEmbedderPolicy: 'require-corp',
crossOriginResourcePolicy: 'same-origin',
// Permissions Policy
permissionsPolicy: {
camera: [],
microphone: [],
geolocation: ['self'],
},
},
});
await server.start();
```
### Security Headers Reference
| Header | Option | Description |
|--------|--------|-------------|
| `Content-Security-Policy` | `csp` | Controls resources the browser can load |
| `Strict-Transport-Security` | `hstsMaxAge`, `hstsIncludeSubDomains`, `hstsPreload` | Forces HTTPS connections |
| `X-Frame-Options` | `xFrameOptions` | Prevents clickjacking attacks |
| `X-Content-Type-Options` | `xContentTypeOptions` | Prevents MIME-sniffing |
| `X-XSS-Protection` | `xXssProtection` | Legacy XSS filter (still useful) |
| `Referrer-Policy` | `referrerPolicy` | Controls referrer information |
| `Permissions-Policy` | `permissionsPolicy` | Controls browser features |
| `Cross-Origin-Opener-Policy` | `crossOriginOpenerPolicy` | Isolates browsing context |
| `Cross-Origin-Embedder-Policy` | `crossOriginEmbedderPolicy` | Controls cross-origin embedding |
| `Cross-Origin-Resource-Policy` | `crossOriginResourcePolicy` | Controls cross-origin resource sharing |
## 📋 Configuration Reference
### IServerOptions
@@ -213,6 +281,7 @@ const swClient = await getServiceworkerClient({
| `defaultAnswer` | `function` | - | Custom default response handler |
| `feedMetadata` | `object` | - | RSS feed metadata options |
| `blockWaybackMachine` | `boolean` | `false` | Block Wayback Machine archiving |
| `securityHeaders` | `ISecurityHeaders` | - | Security headers configuration (CSP, HSTS, etc.) |
## 🏗️ Package Exports
@@ -228,21 +297,57 @@ const swClient = await getServiceworkerClient({
## 🔄 Utility Servers
Pre-configured server templates for common use cases:
Pre-configured server templates with best practices built-in:
### UtilityWebsiteServer
Optimized for modern web applications with SPA support enabled by default:
```typescript
import { utilityservers } from '@api.global/typedserver';
// WebsiteServer - optimized for static websites
const websiteServer = new utilityservers.WebsiteServer({
const websiteServer = new utilityservers.UtilityWebsiteServer({
serveDir: './dist',
domain: 'example.com',
// SPA fallback enabled by default (serves index.html for client routes)
spaFallback: true, // default: true
// Optional security headers
securityHeaders: {
csp: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
},
xFrameOptions: 'SAMEORIGIN',
xContentTypeOptions: true,
},
// Other options
cors: true, // default: true
forceSsl: false, // default: false
appSemVer: '1.0.0',
});
// ServiceServer - optimized for API services
const serviceServer = new utilityservers.ServiceServer({
cors: true,
await websiteServer.start(); // Default port 3000
```
### UtilityServiceServer
Optimized for API services:
```typescript
import { utilityservers } from '@api.global/typedserver';
const serviceServer = new utilityservers.UtilityServiceServer({
serviceName: 'My API',
serviceVersion: '1.0.0',
serviceDomain: 'api.example.com',
port: 8080,
});
await serviceServer.start();
```
## License and Legal Information