exisjs/middleware
The exisjs/middleware module provides the built-in HTTP middleware pipeline for ExisJS. It includes traffic controls, multipart upload handlers, security header suites, and request context enhancers.
Module Exports
import { // Core & Security cors, helmet, csrf, hpp, mongoSanitize, blockSuspiciousProbes, timingSafeEqual, timeout, routeTimeout,
// Traffic & Reliability rateLimit, idempotent, dedupe, ipFilter, backpressure, compression,
// Multipart File Uploads fileUpload, fromExpress,
// Utilities & Observability requestId, requestLogger, serveStatic, validate, conditionalGet,} from 'exisjs/middleware'
import type { CorsConfig, RateLimitOptions, IdempotencyOptions, IpFilterOptions, FileUploadOptions, FileUploadLimits, UploadedFile, BlockProbesOptions, TimeoutOptions, CompressionOptions,} from 'exisjs/middleware'1. Security & Header Middlewares
helmet(options?)
Sets standard HTTP response headers for protection against XSS, clickjacking, MIME sniffing, and protocol downgrades.
function helmet(options?: HelmetOptions): Handler| Option | Type | Default | Description |
|---|---|---|---|
contentSecurityPolicy | boolean | object | false | Configures Content Security Policy (Content-Security-Policy). |
xFrameOptions | 'DENY' | 'SAMEORIGIN' | 'SAMEORIGIN' | Protects against clickjacking. |
hsts | boolean | HstsOptions | true (in prod) | Strict Transport Security configuration. |
noSniff | boolean | true | Sets X-Content-Type-Options: nosniff. |
xssFilter | boolean | true | Sets X-XSS-Protection: 0, disabling the legacy browser XSS auditor (current OWASP guidance). |
cors(config?)
Manages Cross-Origin Resource Sharing headers, preflight OPTIONS responses, and allowed credentials.
function cors(config?: CorsConfig): Handler| Option | Type | Default | Description |
|---|---|---|---|
origin | string | RegExp | string[] | boolean | CorsOriginFn | '*' | Allowed origin(s) or dynamic resolver function. |
methods | string[] | ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'] | Allowed HTTP methods. |
allowedHeaders | string[] | ['Content-Type', 'Authorization', 'Accept', 'Origin', ...] | Allowed request headers. |
exposedHeaders | string[] | [] | Headers exposed to client scripts. |
credentials | boolean | false | Sets Access-Control-Allow-Credentials: true. |
maxAge | number | 86400 | Preflight cache lifetime in seconds. |
csrf(options?)
Enforces Cross-Site Request Forgery protection using the Signed Double-Submit Cookie pattern.
function csrf(options?: CsrfOptions): HandlerblockSuspiciousProbes(options?)
Detects and drops malicious vulnerability scanners probing for sensitive assets (.env, .git, wp-login.php) before they hit route logic or flood log streams.
function blockSuspiciousProbes(options?: BlockProbesOptions): Handlerhpp(options?)
Protects against HTTP Parameter Pollution by normalizing repeated query parameters.
function hpp(options?: HppOptions): HandlermongoSanitize(options?)
Strips $ and . prefixes from request parameters and body fields to mitigate NoSQL injection vectors.
function mongoSanitize(options?: MongoSanitizeOptions): Handler2. Traffic, Rate Limiting & Reliability
rateLimit(options?)
In-memory fixed-window rate limiter; expired windows are swept automatically.
function rateLimit(options?: RateLimitOptions): Handler| Option | Type | Default | Description |
|---|---|---|---|
windowMs | number | 60000 (1 min) | Time window in milliseconds. |
max | number | 100 | Maximum allowed requests within the time window. |
keyGenerator | (req: Request) => string | req => req.ip | Custom partition key generator. |
message | string | object | 'Too many requests' | Response payload on rate limit breach. |
statusCode | number | 429 | HTTP status code for throttled requests. |
timeout(options?) & routeTimeout(msOrOptions)
Terminates long-running requests that exceed the specified threshold, returning 503 Service Unavailable.
function timeout(options?: TimeoutOptions): Handlerfunction routeTimeout(msOrOptions: number | TimeoutOptions): Handler| Option | Type | Default | Description |
|---|---|---|---|
ms | number | 60000 | Timeout threshold in milliseconds. |
statusCode | number | 503 | Response status code upon timeout. |
message | string | 'Service Unavailable' | Error message sent to client. |
exclude | (string | RegExp)[] | [] | Path patterns exempt from timeout rules. |
idempotent(options?)
Caches responses against the Idempotency-Key HTTP header in a bounded in-memory cache (10,000 entries) to prevent duplicate mutations.
function idempotent(options?: IdempotencyOptions): Handler| Option | Type | Default | Description |
|---|---|---|---|
ttlMs | number | 86400000 (24h) | Cache entry time-to-live in milliseconds. |
header | string | 'idempotency-key' | Target HTTP request header name. |
dedupe(options?)
Prevents identical concurrent in-flight requests from being computed more than once simultaneously.
function dedupe(options?: DedupeOptions): HandleripFilter(options)
Applies CIDR-compatible IP allow-lists or deny-lists to restrict access to trusted networks.
function ipFilter(options: IpFilterOptions): Handler| Option | Type | Description |
|---|---|---|
allow | string[] | Array of permitted IP addresses or CIDR blocks (e.g. ['10.0.0.0/8', '192.168.1.5']). |
deny | string[] | Array of blocked IP addresses or CIDR blocks. |
The address checked is req.ip. Behind a proxy or load balancer, set trustProxy in exis.config.ts so req.ip is the real client; ipFilter never reads X-Forwarded-For itself, because a client can send any value in that header.
backpressure(options?)
Monitors Node.js Event Loop lag in real-time, returning 503 when lag exceeds safe thresholds.
function backpressure(options?: BackpressureOptions): Handlercompression(options?)
Applies Gzip, Deflate, or Brotli compression to response streams when requested by the client Accept-Encoding header.
function compression(options?: CompressionOptions): Handler3. Multipart File Uploads
fileUpload
Streaming multipart/form-data upload middleware providing single, array, and field configurations.
// Single file uploadfileUpload.single(fieldName: string, options?: FileUploadOptions): Handler
// Multiple files under the same field namefileUpload.array(fieldName: string, maxCount?: number, options?: FileUploadOptions): Handler
// Multiple distinct fieldsfileUpload.fields(fields: { name: string; maxCount?: number }[], options?: FileUploadOptions): Handler
// Any files acceptedfileUpload.any(options?: FileUploadOptions): Handler
// Text fields onlyfileUpload.none(options?: FileUploadOptions): HandlerFileUploadOptions
| Option | Type | Description |
|---|---|---|
dest | string | Target directory on disk to stream uploaded files to. |
maxBytes | number | Maximum allowed individual file size in bytes. |
mimeTypes | string[] | Permitted MIME types (e.g. ['image/png', 'image/jpeg']). |
limits | FileUploadLimits | Detailed limits (fileSize, files, fieldSize, fields, parts). |
Default limits (applied when a route does not set its own): files: 10, fields: 100, parts: 200, fieldSize: 1 MB, and fileSize equal to the app bodyLimit (10 MB by default). Exceeding a limit returns 413 Payload Too Large. Files written to disk are named <field>-<uuid><ext>; field names and extensions are sanitized, so client input cannot choose the path.
Example
import { controller, route } from 'exisjs/router'import { fileUpload } from 'exisjs/middleware'
export default controller({ uploadAvatar: route.post('/avatar', { middleware: [fileUpload.single('avatar', { maxBytes: 5 * 1024 * 1024, mimeTypes: ['image/png', 'image/jpeg'], })], async handle({ req }) { const file = req.file // UploadedFile { filename, originalname, mimetype, size, buffer } return { success: true, filename: file.filename } }, }),})fromExpress(middleware)
Adapts standard Express/Connect middleware to run within the ExisJS pipeline.
import { fromExpress } from 'exisjs/middleware'import morgan from 'morgan'
app.use(fromExpress(morgan('combined')))4. Utility Middlewares
| Middleware | Signature | Description |
|---|---|---|
requestId() | () => Handler | Injects a unique X-Request-Id into request and response headers. |
requestLogger(options?) | (options?: LoggerConfig) => Handler | Formats and logs request completion timings and status codes. |
serveStatic(root, options?) | (root: string, options?: StaticOptions) => Handler | Serves static assets from disk with caching headers and streaming backpressure. |
conditionalGet() | () => Handler | Turns on automatic ETags and 304 Not Modified for the routes it is applied to (as etag: true does app-wide). |
validate(schema) | (schema: ValidateSchema) => Handler | Validates request parameters against a TexEngine schema. |