Create CORS middleware with surgical security validation
Integration Trap: Must register before route handlers to catch preflight OPTIONS requests. Security Constraint: Cannot combine wildcard origins with credentials per RFC 6454. Performance Note: Origin functions called for every request - keep validation logic fast.
Optional
options: { CORS configuration options
Request headers whitelist
Allow cookies/authorization headers (requires specific origins)
Response headers visible to client JavaScript
Middleware identifier for debugging
Preflight cache duration in seconds
Allowed HTTP methods
Origin validation strategy
// Allow all origins - good for development
const cors = new CORS({
origin: true,
credentials: false // Required with wildcard origins
});
// Strict origin control for production
const cors = new CORS({
origin: ['https://myapp.com', 'https://admin.myapp.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 3600 // 1 hour cache
});
// Allow all subdomains of myapp.com
const cors = new CORS({
origin: /^https://.*\.myapp\.com$/,
credentials: true
});
// Custom origin validation logic
const cors = new CORS({
origin: (origin) => {
// Allow localhost in development
if (process.env.NODE_ENV === 'development') {
return origin?.includes('localhost');
}
// Production whitelist
return ['https://myapp.com', 'https://admin.myapp.com'].includes(origin);
}
});
Gets the middleware handler function.
Returns the function that will be executed when the middleware runs. This getter provides read-only access to the handler function.
The handler function
const middleware = new Middleware((ctx) => {
console.log('Processing request');
});
const handler = middleware.handler;
console.log(typeof handler); // 'function'
// Can be used for testing or introspection
if (handler.toString().includes('console.log')) {
console.log('This middleware includes logging');
}
Gets the middleware identifier.
Returns the identifier string or null if no identifier was set. This getter provides read-only access to the identifier.
The identifier or null if not set
// Middleware with identifier
const authMiddleware = new Middleware((ctx) => {}, 'auth');
console.log(authMiddleware.identifier); // 'auth'
// Middleware without identifier
const loggingMiddleware = new Middleware((ctx) => {});
console.log(loggingMiddleware.identifier); // null
// Use identifier for conditional logic
if (middleware.identifier === 'authentication') {
console.log('This is an authentication middleware');
}
Executes the middleware handler with the given context.
This method invokes the middleware handler function, passing the context object as the first argument. The method supports both synchronous and asynchronous handlers, always returning a Promise.
Execution Flow:
Error Handling: Any errors thrown by the handler (synchronous or asynchronous) are propagated to the caller. This allows middleware errors to be handled by the calling code.
The request/response context
Promise that resolves when the handler completes
const middleware = new Middleware((ctx) => {
console.log(`Processing ${ctx.method} request to ${ctx.path}`);
ctx.data.processedAt = new Date().toISOString();
});
const url = new URL('http://localhost/api/users');
const ctx = new Context('GET', url, new Headers());
// Execute middleware
await middleware.execute(ctx);
console.log(ctx.data.processedAt); // ISO timestamp
// Async middleware
const asyncMiddleware = new Middleware(async (ctx) => {
await new Promise(resolve => setTimeout(resolve, 100));
ctx.data.asyncProcessed = true;
});
await asyncMiddleware.execute(ctx);
console.log(ctx.data.asyncProcessed); // true
// Error handling
const errorMiddleware = new Middleware((ctx) => {
throw new Error('Middleware error');
});
try {
await errorMiddleware.execute(ctx);
} catch (error) {
console.error('Middleware failed:', error.message);
}
// Invalid context
try {
await middleware.execute(null);
} catch (error) {
console.error(error.message); // "Context must be a Context instance"
}
Checks if this middleware has the same identifier as another middleware.
This method is used for duplicate detection and middleware comparison. Two middleware are considered to have the same identifier if:
Note: Middleware with null identifiers are never considered equal, even if both have null identifiers.
The other middleware to compare with
True if both middlewares have the same non-null identifier
const auth1 = new Middleware((ctx) => {}, 'authentication');
const auth2 = new Middleware((ctx) => {}, 'authentication');
const logging = new Middleware((ctx) => {}, 'logging');
const generic = new Middleware((ctx) => {});
// Same identifier
auth1.hasSameIdentifier(auth2); // true
auth2.hasSameIdentifier(auth1); // true
// Different identifiers
auth1.hasSameIdentifier(logging); // false
logging.hasSameIdentifier(auth1); // false
// Null identifiers (never equal)
auth1.hasSameIdentifier(generic); // false
generic.hasSameIdentifier(auth1); // false
generic.hasSameIdentifier(new Middleware((ctx) => {})); // false
// Invalid parameters
auth1.hasSameIdentifier(null); // false
auth1.hasSameIdentifier({}); // false
auth1.hasSameIdentifier('string'); // false
// Use for duplicate prevention
function addMiddlewareIfNotExists(middlewareList, newMiddleware) {
const hasDuplicate = middlewareList.some(existing =>
existing.hasSameIdentifier(newMiddleware)
);
if (!hasDuplicate) {
middlewareList.push(newMiddleware);
}
}
CORS - Cross-Origin Resource Sharing Middleware
This middleware provides comprehensive CORS support for Wings applications, handling both preflight OPTIONS requests and regular request CORS headers. It follows the CORS specification (RFC 6454) and WHATWG CORS standard to ensure proper cross-origin request handling.
CORS Fundamentals
CORS is a security mechanism that uses HTTP headers to tell browsers which origins are allowed to access a web API from client-side JavaScript. Without proper CORS configuration, browsers will block cross-origin requests to protect users from malicious scripts.
The middleware handles two types of requests:
Origin Configuration
The origin option supports multiple configuration patterns for maximum flexibility:
'https://myapp.com'
)['https://app1.com', 'https://app2.com']
)/^https://.*\.myapp\.com$/
)(origin) => isAllowed(origin)
)true
for wildcard,false
to disable CORS'*'
allows all origins (not recommended with credentials)Security Considerations
*
) cannot be used with credentials for securityExample: Basic CORS (Allow All Origins)
Example: Production CORS (Specific Origins)
Example: Dynamic Origin Validation
Example: API-Specific CORS