Skip to content

Instantly share code, notes, and snippets.

@alexjs
Forked from michiel/cors-nginx.conf
Created November 28, 2012 22:42
Show Gist options
  • Save alexjs/4165271 to your computer and use it in GitHub Desktop.
Save alexjs/4165271 to your computer and use it in GitHub Desktop.
Slightly tighter CORS config for nginx
#
# Slightly tighter CORS config for nginx
#
# A modification of https://gist.github.com/1064640/ to include a white-list of URLs
#
# Despite the W3C guidance suggesting that a list of origins can be passed as part of
# Access-Control-Allow-Origin headers, several browsers (well, at least Firefox)
# don't seem to play nicely with this.
#
# To avoid the use of 'Access-Control-Allow-Origin: *', use a simple-ish whitelisting
# method to control access instead.
#
# NB: This relies on the use of the 'Origin' HTTP Header.
location / {
if ($http_origin ~* (whitelist\.address\.one|whitelist\.address\.two)) {
set $cors "true";
}
# Nginx doesn't support nested If statements. This is where things get slightly nasty.
# Determine the HTTP request method used
if ($request_method = 'OPTIONS') {
set $cors "${cors}options";
}
if ($request_method = 'GET') {
set $cors "${cors}get";
}
if ($request_method = 'POST') {
set $cors "${cors}post";
}
if ($cors = "true") {
# Catch all incase there's a request method we're not dealing with properly
add_header 'Access-Control-Allow-Origin' "$http_origin";
}
if ($cors = "trueget") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($cors = "trueoptions") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($cors = "truepost") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
@programarivm
Copy link

If you're using PHP this basic set up may help.

default.conf

server {
    listen 443 ssl;
    server_name             pgn-chess-data.local;
    ssl_certificate         /etc/nginx/ssl/pgn-chess-data.local.crt;
    ssl_certificate_key     /etc/nginx/ssl/pgn-chess-data.local.key;
    ssl_ciphers             EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
    ssl_protocols           TLSv1.1 TLSv1.2;

    root /usr/share/nginx/pgn-chess-data/public;

    client_max_body_size 20M;

    location ~ ^/api/ {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/.+\.php(/|$) {
        fastcgi_pass php_fpm:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

public/index.php

<?php

require realpath(dirname(__FILE__)) .'/../src/bootstrap.php';

header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range");

switch (true) {
    case '/api/query' === $_SERVER['REQUEST_URI'] && $_SERVER['REQUEST_METHOD'] === 'POST':
        require APP_PATH . '/src/Api/Query.php';
        exit;
    case $_SERVER['REQUEST_METHOD'] === 'OPTIONS':
        http_response_code(204);
        exit;
    default:
        http_response_code(404);
        exit;
}

@tonykor
Copy link

tonykor commented Dec 6, 2020

Hello, I have fixed try_files problem next way

server {
    server_name api.domain.com;
    set $cors "https://domain.com";
    if ($http_origin ~* (/|\.)domain\.(com|dev)$) {
        set $cors $http_origin;
    }
    add_header 'Access-Control-Allow-Origin' '$cors' always;
    ...
    ...
    ...
    location / {
       try_files $uri $uri/ /index.php$is_args$args;
    }
}

@BlackTurtle123
Copy link

BlackTurtle123 commented Apr 13, 2021

For me something like this broke my preflight check for cors and therefor failing cors for some reason...

` gzip off;
proxy_set_header X-Forwarded-Ssl on;
client_max_body_size 50M;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_pass http://test.app_backend;

  set $cors "";

  if ($http_origin ~* (.*\.test.app|https://waves.exchange|.*\.test2.app|.*\.wallet.com)) {
    set $cors "true";
  }
  if ($cors = "true") {
  add_header 'Access-Control-Allow-Origin' "$http_origin" always;
  add_header 'Access-Control-Allow-Credentials' 'true' always;
  add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
  add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,signature,timestamp' always;
  add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
  }
  if ($request_method = 'OPTIONS') {
    return 204;
  }

`

@luohoufu
Copy link

work for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment