corsMiddleware function
Middleware
corsMiddleware({
- List<
String> ? allowedOrigins, - List<
String> allowedMethods = const ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], - List<
String> allowedHeaders = const ['Origin', 'Content-Type', 'Accept', 'Authorization', 'X-CSRF-Token'], - List<
String> exposedHeaders = const [], - bool allowCredentials = true,
- int maxAge = 86400,
CORS Middleware for handling Cross-Origin Resource Sharing
Example usage:
final handler = Pipeline()
.addMiddleware(corsMiddleware(
allowedOrigins: ['https://example.com', 'https://app.example.com'],
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE'],
))
.addHandler(router);
Implementation
Middleware corsMiddleware({
List<String>? allowedOrigins,
List<String> allowedMethods = const ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
List<String> allowedHeaders = const ['Origin', 'Content-Type', 'Accept', 'Authorization', 'X-CSRF-Token'],
List<String> exposedHeaders = const [],
bool allowCredentials = true,
int maxAge = 86400, // 24 hours
}) {
return (Handler handler) {
return (Request request) async {
final origin = request.headers['origin'];
// Check if origin is allowed
bool isOriginAllowed = false;
if (allowedOrigins == null || allowedOrigins.isEmpty) {
// In development, allow all origins
isOriginAllowed = true;
} else if (origin != null) {
isOriginAllowed = allowedOrigins.any((allowed) {
if (allowed == '*') return true;
if (allowed.endsWith('*')) {
final prefix = allowed.substring(0, allowed.length - 1);
return origin.startsWith(prefix);
}
return origin == allowed;
});
}
// Handle preflight OPTIONS request
if (request.method == 'OPTIONS') {
return Response.ok(
null,
headers: {
if (isOriginAllowed && origin != null) 'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': allowedMethods.join(', '),
'Access-Control-Allow-Headers': allowedHeaders.join(', '),
if (exposedHeaders.isNotEmpty) 'Access-Control-Expose-Headers': exposedHeaders.join(', '),
if (allowCredentials) 'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': maxAge.toString(),
},
);
}
// Process actual request
final response = await handler(request);
// Add CORS headers to response
return response.change(headers: {
if (isOriginAllowed && origin != null) 'Access-Control-Allow-Origin': origin,
if (exposedHeaders.isNotEmpty) 'Access-Control-Expose-Headers': exposedHeaders.join(', '),
if (allowCredentials) 'Access-Control-Allow-Credentials': 'true',
});
};
};
}