DEV3 Technologies home

DEV3 Developer Forum

How do I fix a CORS error by adding the right headers in Nginx or Apache?

DevOps helpSolved0 views

1 reply

dev3 · Accepted answer

CORS is enforced by the browser. The server must answer with headers that allow the requesting origin. The fix belongs on the API side (the app framework is usually the best place, but it can be done in the web server).

What a browser needs

  • Simple requests: Access-Control-Allow-Origin in the response.
  • Requests with JSON bodies, custom headers like Authorization, or methods like PUT/DELETE trigger a preflight OPTIONS request, which must return 2xx with Access-Control-Allow-Methods and Access-Control-Allow-Headers.

Nginx (allow one specific origin, never a blind * with credentials):

location /api/ {
    if ($http_origin = "https://app.example.com") {
        set $cors_origin $http_origin;
    }
    add_header Access-Control-Allow-Origin $cors_origin always;
    add_header Vary Origin always;

    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Origin $cors_origin always;
        add_header Vary Origin always;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
        add_header Access-Control-Max-Age 86400;
        return 204;
    }
    proxy_pass http://127.0.0.1:3000;
}

Apache: with mod_headers:

Header always set Access-Control-Allow-Origin "https://app.example.com"
Header always set Access-Control-Allow-Headers "Authorization, Content-Type"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"

Pitfalls

  • Duplicate headers: if both your app and Nginx add Access-Control-Allow-Origin, browsers reject the response. Set it in one place.
  • always is needed so headers are also sent on error responses (401, 500), otherwise the browser reports CORS instead of the real error.
  • With cookies, use Access-Control-Allow-Credentials: true and an explicit origin (not *), and set credentials: 'include' on the client.
  • Redirects on preflight fail; call the final URL.

Test with curl -i -X OPTIONS -H "Origin: https://app.example.com" -H "Access-Control-Request-Method: POST" https://api.example.com/api/x, or use the CORS checker.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.