wildcard cors
A more up-to-date answer:
#
# Wide-open CORS config for nginx
#
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-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-CustomHeader,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 ($request_method = 'POST') {
add_header 'Access-Control-Allow-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-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-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-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
source: https://michielkalkman.com/snippets/nginx-cors-open-configuration.html
You may also wish to add Access-Control-Expose-Headers
(in the same format as Access-Control-Allow-Headers) in order to expose your custom and/or ‘non-simple’ headers to ajax requests.
Access-Control-Expose-Headers (optional) - The XMLHttpRequest 2 object has a
getResponseHeader() method that returns the value of a particular response
header. During a CORS request, the getResponseHeader() method can only access
simple response headers. Simple response headers are defined as follows:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
If you want clients to be able to access other headers, you have to use the
Access-Control-Expose-Headers header. The value of this header is a comma-
delimited list of response headers you want to expose to the client.
-http://www.html5rocks.com/en/tutorials/cors/
Configs for other web servers http://enable-cors.org/server.html
Access-Control-Allow-Credentials
If you’re using Access-Control-Allow-Credentials with your CORS request you’ll want the cors header wiring within your location to resemble this.
As the origin has to match the client domain, wildcard doesn’t work.
if ($http_origin = ''){
set $http_origin "*";
}
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin $http_origin;
Выделил для API отдельный поддомен и отдельный SSL-сертификат. Вот такой конфиг:
upstream keeper_app {
server 127.0.0.1:8080;
}
server {
listen 443 ssl http2;
server_name api.domain.ru www.api.domain.ru;
access_log /var/log/nginx/api.domain.ru/access.log combined;
error_log /var/log/nginx/api.domain.ru/error.log warn;
ssl_certificate /etc/ssl/api.domain.ru/api.domain.ru.crt;
ssl_certificate_key /etc/ssl/api.domain.ru/api.domain.ru.key;
resolver 8.8.8.8 8.8.8.4 valid=300s;
ssl_stapling on;
ssl on;
ssl_session_cache shared:SSL:2m;
ssl_session_timeout 24h;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers kEECDH+AES128:kEECDH:kEDH:-3DES:kRSA+AES128:kEDH+3DES:DES-CBC3-SHA:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv2;
ssl_dhparam /etc/ssl/api.domain.ru/api.domain.ru.dh2048.pem;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
add_header 'Access-Control-Allow-Origin' 'https://domain.ru';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header Access-Control-Allow-Credentials 'true';
location ~ ^/(favicon.ico)$ {
access_log off;
}
location / {
proxy_pass http://keeper_app/api/v1$request_uri;
}
}
Запросы с основного домена идут с помощью сервиса Angular $http. Добавил строку в конфиг angular модуля:$httpProvider.defaults.withCredentials = true;
В итоге при любом обращении с domain.ru на api.domain.ru получаю это:
XMLHttpRequest cannot load https://api.domain.ru/user/valid. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://domain.ru' is therefore not allowed access. The response had HTTP status code 401.
Что не так?
The issue is that your if condition is not going to send the headers in the parent in /
. If you check the preflight response headers it would be
HTTP/1.1 204 No Content
Server: nginx/1.13.3
Date: Fri, 01 Sep 2017 05:24:04 GMT
Connection: keep-alive
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=UTF-8
Content-Length: 0
And that doesn’t give anything. So two possible fixes for you. Copy the add_header
inside if block also
server {
listen 80;
server_name api.localhost;
location / {
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
}
}
Or you can move it outside the location block, so every request has the response
server {
listen 80;
server_name api.localhost;
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000;
}
}
If you only want to allow certain locations in your config for CORS. like /api
then you should create a template conf with your headers
add_header 'Access-Control-Allow-Origin' 'http://api.localhost';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
and then use
include conf.d/corsheaders.conf;
in your OPTIONS
block and /api
block. So CORS are only allowed for the /api
. If you don’t care which location for CORS then you can use the second approach of moving core headers to server block
By default, cross domain requests (also called CORS – Cross Origin Resource Sharing) are disabled in NGINX. You need to enable CORS in NGINX to allow cross-domain requests in NGINX. Here’s how to allow CORS in NGINX to allow cross domain requests in NGINX.
Here are the steps to enable CORS in NGINX.
In order to allow CORS in NGINX, you need to add add_header Access-Control-Allow-Origin directive in server block of your NGINX server configuration, or virtual host file.
1. Open NGINX Server Configuration
Open terminal and run the following command to open NGINX server configuration file.
$ sudo vi /etc/nginx/nginx.conf
If you have configured separate virtual hosts for your website (e.g www.website.com), such as /etc/nginx/sites-enabled/website.conf then open its configuration with the following command
$ sudo vi /etc/nginx/sites-enabled/website.conf
Bonus Read : How to Install NGINX in Ubuntu
2. Enable CORS in NGINX
Add add_header directive to server block of your NGINX configuration file.
server{ ... add_header Access-Control-Allow-Origin *; ... }
There are different configuration options available for enabling CORS in NGINX.
Enable CORS from all websites
If you want to enable CORS for all websites, that is, accept cross domain requests from all websites, add the following
add_header Access-Control-Allow-Origin *;
In the above statement, we use wildcard (*) for NGINX Access-Control-Allow-Origin directive
Bonus Read : How to Enable TLS 1.3 in NGINX
Enable CORS from one domain
If you want to enable CORS for one website domain (e.g example.com), specify that domain in place of wildcard character *.
add_header Access-Control-Allow-Origin "example.com";
Enable CORS from multiple domains
If you want to enable CORS for multiple domains (e.g example1.com, example2.com,example3.com), specify them separately one after another
add_header Access-Control-Allow-Origin "example1.com"; add_header Access-Control-Allow-Origin "example2.com"; add_header Access-Control-Allow-Origin "example3.com";
Enable CORS from localhost
If you want to enable CORS from localhost, add 127.0.0.1 or localhost in place of domain name
add_header Access-Control-Allow-Origin "localhost";
Bonus Read : How to Fix 500 Internal Server Error in NGINX
3. Restart NGINX Server
Finally, run the following command to check syntax of your updated config file.
$ sudo nginx -t
If there are no errors, run the following command to restart NGINX server.
$ sudo service nginx reload #debian/ubuntu $ systemctl restart nginx #redhat/centos
You can use free online tools like Test CORS to test if your website accepts CORS.
That’s it! Hopefully the above tutorial will help you enable CORS in NGINX.
Ubiq makes it easy to visualize data in minutes, and monitor in real-time dashboards. Try it today!
Related posts:
- About Author
wildcard cors
A more up-to-date answer:
#
# Wide-open CORS config for nginx
#
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-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-CustomHeader,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 ($request_method = 'POST') {
add_header 'Access-Control-Allow-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-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-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-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
source: https://michielkalkman.com/snippets/nginx-cors-open-configuration.html
You may also wish to add Access-Control-Expose-Headers
(in the same format as Access-Control-Allow-Headers) in order to expose your custom and/or ‘non-simple’ headers to ajax requests.
Access-Control-Expose-Headers (optional) - The XMLHttpRequest 2 object has a
getResponseHeader() method that returns the value of a particular response
header. During a CORS request, the getResponseHeader() method can only access
simple response headers. Simple response headers are defined as follows:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
If you want clients to be able to access other headers, you have to use the
Access-Control-Expose-Headers header. The value of this header is a comma-
delimited list of response headers you want to expose to the client.
-http://www.html5rocks.com/en/tutorials/cors/
Configs for other web servers http://enable-cors.org/server.html
Access-Control-Allow-Credentials
If you’re using Access-Control-Allow-Credentials with your CORS request you’ll want the cors header wiring within your location to resemble this.
As the origin has to match the client domain, wildcard doesn’t work.
if ($http_origin = ''){
set $http_origin "*";
}
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin $http_origin;
Example Nginx configuration for adding cross-origin resource sharing (CORS) support to reverse proxied APIs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# CORS header support | |
# | |
# One way to use this is by placing it into a file called «cors_support» | |
# under your Nginx configuration directory and placing the following | |
# statement inside your **location** block(s): | |
# | |
# include cors_support; | |
# | |
# As of Nginx 1.7.5, add_header supports an «always» parameter which | |
# allows CORS to work if the backend returns 4xx or 5xx status code. | |
# | |
# For more information on CORS, please see: http://enable-cors.org/ | |
# Forked from this Gist: https://gist.github.com/michiel/1064640 | |
# | |
set $cors »; | |
if ($http_origin ~ ‘^https?://(localhost|www.yourdomain.com|www.yourotherdomain.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, PUT, DELETE, OPTIONS’ always; | |
add_header ‘Access-Control-Allow-Headers’ ‘Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With’ always; | |
# required to be able to read Authorization header in frontend | |
#add_header ‘Access-Control-Expose-Headers’ ‘Authorization’ always; | |
} | |
if ($request_method = ‘OPTIONS’) { | |
# 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; | |
} |
Nginx Access-Control-Allow-Origin header is part of CORS standard (stands for Cross-origin resource sharing) and used to control access to resources located outside of the original domain sending the request.
This standard was created to overcome same-origin security restrictions in browsers, that prevent loading resources from different domains. With the raise of single page apps relying heavily on external API’s and JavaScript apps in general, the need for CORS server configuration is greater than ever. Please note that Fonts ( @font-face within CSS ) and potentially other resources are also affected by same-origin policy.
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
Wake up, Neo… The matrix has you…
Join our growing UNDERGROUND MOVEMENT of Rain Makers. Just drop your email below and your life will never be the same again.
Feel free to reach out on Twitter, Facebook or Instagram.
CORS (cross-origin resource sharing) — совместное использование ресурсов между разными источниками. Это спецификация, которая обеспечивает действительно открытый доступ между доменами. Если вы размещаете общедоступный контент, рассмотрите возможность использования CORS, чтобы открыть его для универсального доступа из JavaScript в браузерах.
До недавнего времени основным способом преодоления ограничений, наложенных в same-origin-policy относительно XSS запросов, было использование JSONP. Сам JSONP имеет неустранимое ограничение — позволяет только получение данных GET методом, то есть отправка данных через POST метод остается недоступной.
Почему CORS важен?
За последние годы JavaScript и веб-программирование активно развиваются, но same-origin политику никто не отменял. Это препятствует тому, чтобы JavaScript делал запросы между разными доменами, что породило различные хаки для выполнения междоменных запросов.
CORS представляет стандартный механизм, который может использоваться всеми браузерами для реализации междоменных запросов. Спецификация определяет набор заголовков, которые позволяют браузеру и серверу сообщать о том, какие запросы разрешены (и не разрешены). CORS продолжает дух открытой сети, предоставляя доступ к API всем.
Правило ограничения домена (Same Origin Policy, Принцип одинакового источника) — это важная концепция безопасности для некоторых языков программирования на стороне клиента, таких как JavaScript. Политика разрешает сценариям, находящимся на страницах одного сайта, доступ к методам и свойствам друг друга без ограничений, но предотвращает доступ к большинству методов и свойств для страниц на разных сайтах. Одинаковые источники — это источники, у которых совпадают три признака: домен, порт и протокол.
Концепция правила ограничения домена появилась во времена Netscape Navigator 2.0. Скрытые производные оригинальной разработки используются во всех современных браузерах, а также в плагинах, таких как Adobe Flash либо для механизмов отличных от DOM манипуляций, таких как XMLHttpRequest.
Как это работает?
ля инициации Cross-origin запроса браузер клиента добавляет в HTTP запрос Origin (домен сайта, с которого происходит запрос). Например страница http://www.a.com/page.html пытается получить данные со страницы http://www.b.com/cors.txt. В случае если браузер клиента поддерживает технологию CORS, запрос будет выглядеть так:
GET /cors.txt HTTP/1.1 Host: www.b.com Origin: www.a.com
Если сервер www.b.com хочет разрешить получение данных с www.a.com то в ответе сервера будет присутствовать строчка:
Access-Control-Allow-Origin: http://www.a.com
Если в ответе сервера отсутствует данная строка, то браузер поддерживающий технологию CORS, передаст ошибку вместо данных.
В случае, если сервер хочет разрешить доступ любому домену, он может указать в ответе:
Access-Control-Allow-Origin: *
Если сервер хочет разрешить доступ более чем одному домену, то в ответе сервера должно быть по одной строчке Access-Control-Allow-Origin для каждого домена.
Access-Control-Allow-Origin: http://www.a.com Access-Control-Allow-Origin: http://www.b.com Access-Control-Allow-Origin: http://www.c.com
На практике чаще используется запись из нескольких доменов, разделенных пробелом:
Access-Control-Allow-Origin: http://www.a.com http://www.b.com http://www.c.com
Пример конфигурации CORS для web-сервера Nginx
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
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,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# 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 ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
Post Views:
21 200
Last updated: 2015-08-02 ::
Published: 2015-07-19
:: [ history ]
You can also subscribe to the RSS or Atom feed, or follow me on Twitter.
[UPDATE 2015/08/02]
As @OtaK_ pointed out, in most cases CORS should be handled directly by the app as it should return the allowed verbs by endpoint, instead of all of them being allowed by Nginx. This config should only be used for quick development, of a prototype or PoC for example, or if you are certain that the same verbs are allowed for all the endpoints (that would be the case for the assets returned by a CDN, for instance).
[/UPDATE]
With the always wider adoption of API-driven architecture, chances are you already had to deal with cross-origin resource sharing at some point.
Whilst it is possible to deal with it from the code and you will find many packages or snippets to do so, we can remove the CORS handling from our app and let the HTTP server take care of it.
The Enable CORS website contains useful resources to this end, but when I tried to use their Nginx config for my own projects it didn’t quite work as expected.
The following examples are based on the Nginx server configurations generated by Homestead, but the steps won’t change much even if you are not using Laravel’s dev environment.
First of all, Nginx’s traditional add_header
directive doesn’t work with 4xx
responses. As we still want to add custom headers to them, we need to install the ngx_headers_more module to be able to use the more_set_headers
directive, which also works with 4xx
responses.
While the documentation suggests to build the Nginx source with the module, if you are on a Debian distro you can actually easily install it with the nginx-extras package:
sudo apt-get install nginx-extras
The server configuration
Here is what a typical server config of a Laravel project looks like, without the CORS bit (I am voluntarily omitting the SSL part to keep the post short, but it works exactly the same):
server { listen 80; server_name example-site.com; root "/home/vagrant/projects/example-site/public"; index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/example-site.com-error.log error; sendfile off; client_max_body_size 100m; location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_intercept_errors off; fastcgi_buffer_size 16k; fastcgi_buffers 4 16k; } location ~ /.ht { deny all; } }
Now, with the CORS handling:
server { listen 80; server_name example-site.com; root "/home/vagrant/projects/example-site/public"; index index.html index.htm index.php; charset utf-8; more_set_headers 'Access-Control-Allow-Origin: $http_origin'; more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, HEAD'; more_set_headers 'Access-Control-Allow-Credentials: true'; more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization'; location / { if ($request_method = 'OPTIONS') { more_set_headers 'Access-Control-Allow-Origin: $http_origin'; more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, HEAD'; more_set_headers 'Access-Control-Max-Age: 1728000'; more_set_headers 'Access-Control-Allow-Credentials: true'; more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization'; more_set_headers 'Content-Type: text/plain; charset=UTF-8'; more_set_headers 'Content-Length: 0'; return 204; } try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/example-site.com-error.log error; sendfile off; client_max_body_size 100m; location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_intercept_errors off; fastcgi_buffer_size 16k; fastcgi_buffers 4 16k; } location ~ /.ht { deny all; } }
And that is pretty much it.
All you need to do now is to reload your Nginx confs:
sudo service nginx reload
Note that this allows any domain to access your app, and while this is most likely enough for local development, on a production server you might want to fine-tune this configuration to allow specific domains only (Access_Control_Allow_Origin
).
More generally, all the headers’ values are examples and you can modify them as you see fit.
You could also put the global and options-related snippets into separate files (in /etc/nginx/shared/
, for example) and import them with the Nginx’s include
directive.
You can also subscribe to the RSS or Atom feed, or follow me on Twitter.
Last updated by osteel on
2015-08-02
:: [
cors
crossoriginresourcesharing
nginx
homestead
]