CORS on Nginx

Hariom Vashisth
Mar 31, 2018 · 3 min read

Nginx Access-Control-Allow-Origin and CORS

credits: http://jorgearco.com/

Ok, so here is the sample of CORS configuration for Nginx:

server {
listen 80;
server_name api.test.com;


location / {

# Simple requests
if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}

# Preflighted requests
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}

....
# Handle request
....
}
}

As you can tell by Access-Control-Allow-Origin * – this is wide open configuration, meaning any client will be able to access the resource.

You can list specific hostnames that are allowed to access the server:

add_header "Access-Control-Allow-Origin" "http://test.com, https://example.com"

If you wonder what’s if ($request_method = OPTIONS ) condition, you are not alone. There is slightly confusing concept of Simple and Pre-flight CORS requests (see detailed cors spec).

In the nutshell Simple request is GET, HEAD or POST methods without special headers. In this case request looks like this:

and our Nginx config snippet to handle simple requests:

if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}

If the request involves PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH methods or any special headers not listed for the Simple Request ( see the spec link I gave above ), then it’s treated as Preflighted request. Don’t be scared by fancy words here, in case of preflighted request the client needs to send two requests:

OPTIONS request first to verify what’s allowed. Here is our Nginx config part for that:

if ($request_method = OPTIONS ) { add_header "Access-Control-Allow-Origin" *; add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD"; add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept"; return 200; }

Once the client receives the response and checks that original request is allowed. It issues second request with original data.

Here is the diagram to show requests flow:

Here are a couple useful CURL command that I use to test the implementation:

curl -s -D - -H "Origin: http://example.com" https://api.example.com/my-endpoint -o /dev/null

You should see Access-Control-Allow-Origin header if everything look good.

To test Preflighted requests, just add -X OPTIONS like this:

curl -s -D - -H "Origin: http://example.com" -X OPTIONS https://api.example.com/my-endpoint -o /dev/null

If you want dive deeper into Nginx access control allow origin and CORS here is excellent post that I already mentioned before – https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Credits: Sergey Khaladzinski

Hariom Vashisth

Written by

Full Stack Developer || DevOps Engineer || AWS || GCP || Docker || Kubernetes • Now @airtel • Prev @exzeo @SocialCops @itc • RT's NOT Endorsements • 🇮🇳

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade