CORS Middleware Guide
What is CORS?
CORS means Cross-Origin Resource Sharing.
Browsers block frontend applications from calling APIs hosted on a different origin unless the server explicitly allows it.
An origin is:
- protocol (http / https)
- domain
- port
Example:
- http://localhost:5173
- http://localhost:8080These are different origins → CORS is required.
Why CORS exists
Without CORS, any website could call your API using a logged-in user's browser.
CORS allows the server to say:
- Which origins are allowed
- Which HTTP methods are allowed
- Which headers are allowed
- Whether credentials are allowed
1) Basic CORS Example
This allows only https://example.com to call /api.
#include <vix.hpp>
#include <vix/middleware/app/presets.hpp>
using namespace vix;
int main()
{
App app;
app.use("/api", middleware::app::cors_dev({"https://example.com"}));
app.get("/api", [](Request &, Response &res)
{
res.header("X-Request-Id", "req_123");
res.json({ "ok", true });
});
app.run(8080);
}Test
curl -i http://localhost:8080/api -H "Origin: https://example.com"Expected:
- 200 OK
- Access-Control-Allow-Origin header present
2) Strict CORS with Preflight (OPTIONS)
Browsers send a preflight request before certain requests (POST, PUT, custom headers).
This is an OPTIONS request.
You should define explicit OPTIONS routes so the middleware can respond correctly.
#include <vix.hpp>
#include <vix/middleware/app/presets.hpp>
using namespace vix;
int main()
{
App app;
app.use("/api", middleware::app::cors_dev({"https://example.com"}));
app.options("/api", [](Request &, Response &res)
{
res.status(204).send();
});
app.get("/api", [](Request &, Response &res)
{
res.json({ "ok", true });
});
app.run(8080);
}Test allowed origin
curl -i -X OPTIONS http://localhost:8080/api -H "Origin: https://example.com" -H "Access-Control-Request-Method: POST"Expected: 204 + CORS headers.
Test blocked origin
curl -i -X OPTIONS http://localhost:8080/api -H "Origin: https://evil.com" -H "Access-Control-Request-Method: POST"Expected: 403 Forbidden.
3) CORS in Production (Important)
In real applications:
- Apply CORS only on API routes (not public static routes)
- Combine with:
- Security headers
- CSRF protection
- Authentication
- Never allow "*" with credentials
Correct order:
app.use("/api", middleware::app::security_headers_dev());
app.use("/api", middleware::app::cors_dev({"https://example.com"}));
app.use("/api", middleware::app::csrf_dev());Order matters.
Common Beginner Mistakes
- Forgetting OPTIONS route
- Allowing "*" in production
- Not understanding that CORS is enforced by browsers, not curl
- Confusing CORS with authentication (they are different)
Complete Working Example
Save as: cors_app_full.cpp
#include <vix.hpp>
#include <vix/middleware/app/presets.hpp>
using namespace vix;
int main()
{
App app;
app.use("/api", middleware::app::security_headers_dev());
app.use("/api", middleware::app::cors_dev({"https://example.com"}));
app.options("/api/data", [](Request &, Response &res)
{
res.status(204).send();
});
app.get("/api/data", [](Request &, Response &res)
{
res.json({
"ok", true,
"message", "CORS working"
});
});
app.get("/", [](Request &, Response &res)
{
res.send("Public route");
});
app.run(8080);
}Run:
vix run cors_app_full.cppSummary
CORS controls which origins can call your API.
Use:
cors_dev()for development- Explicit OPTIONS routes
- Combine with CSRF and security headers
- Restrict allowed origins in production
CORS is a browser security feature, not an authentication system.