CORS
Cross-Origin Resource Sharing (CORS) controls which browser-based clients from other domains can access your API. Zigmund provides a built-in CORS middleware that handles preflight requests and sets the appropriate response headers.
Overview
Browsers enforce the same-origin policy, blocking JavaScript from making requests to a different domain, port, or protocol unless the server explicitly allows it. CORS headers tell the browser which origins, methods, and headers are permitted.
Zigmund's corsMw() function creates a middleware that automatically responds to OPTIONS preflight requests and attaches CORS headers to every response.
Example
const std = @import("std");
const zigmund = @import("zigmund");
fn corsProtectedEndpoint(allocator: std.mem.Allocator) !zigmund.Response {
return zigmund.Response.json(allocator, .{
.message = "This endpoint is protected by CORS middleware",
});
}
pub fn main() !void {
var app = try zigmund.App.init(.{ .port = 8080 });
try app.addMiddleware(zigmund.corsMw(.{
.allowed_origins = &.{"https://example.com"},
.allowed_methods = &.{ "GET", "POST", "OPTIONS" },
.allowed_headers = &.{ "Content-Type", "Authorization" },
.allow_credentials = true,
.max_age = 3600,
}));
try app.get("/data", corsProtectedEndpoint, .{});
try app.listen();
}
How It Works
- Registration.
zigmund.corsMw()takes a configuration struct and returns azigmund.Middlewarevalue. Pass it toapp.addMiddleware()to install it. - Preflight handling. When the browser sends an
OPTIONSrequest, the middleware responds immediately with the configured CORS headers and a204 No Contentstatus. The route handler is never called. - Normal requests. For non-preflight requests, the middleware adds CORS headers (
Access-Control-Allow-Origin,Access-Control-Allow-Methods, etc.) to the response after the handler runs.
Configuration Options
| Option | Type | Description |
|---|---|---|
allowed_origins |
[]const []const u8 |
Origins permitted to access the API. Use &.{"*"} to allow all origins. |
allowed_methods |
[]const []const u8 |
HTTP methods the client may use. Typically GET, POST, PUT, DELETE, OPTIONS. |
allowed_headers |
[]const []const u8 |
Request headers the client may send. Include Content-Type and Authorization at minimum. |
allow_credentials |
bool |
Whether the browser should include cookies and auth headers in cross-origin requests. Cannot be true if allowed_origins is *. |
max_age |
u32 |
How long (in seconds) the browser should cache the preflight response. 3600 (one hour) is a common value. |
Key Points
- Register CORS middleware early. It should be one of the first middleware registered so that preflight responses are sent before any other middleware runs.
- Wildcard origins. Setting
allowed_originsto&.{"*"}allows any origin. This is convenient for public APIs but incompatible withallow_credentials = true. - Credentials and cookies. When
allow_credentialsistrue, the browser sends cookies and authorization headers with cross-origin requests. TheAccess-Control-Allow-Originheader must be a specific origin, not*. - Preflight caching. A higher
max_agereduces the number of preflightOPTIONSrequests the browser sends, improving performance for frequently called endpoints. - Per-route CORS is not needed. The middleware applies to all routes. If you need different CORS policies for different route groups, use multiple sub-applications or routers with separate middleware stacks.
See Also
- Middleware -- How middleware works in general.
- Bigger Applications -- Using routers for per-group middleware configuration.