Reputation: 900
I have been searching around for CORS request conf in nginx and arrived at this configuration:
server {
listen 80;
server_name apibackend;
root /mnt/www/apibackend/public;
access_log /var/log/nginx/apibackend.access.log;
error_log /var/log/nginx/apibackend.error.log;
# serve static files directly
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}
location /{
index index.html index.htm index.php; #try static .html file first
try_files $uri $uri/ /index.php?q=$uri&$args;
}
# catch all
error_page 404 /index.php;
location ~ \.php$ {
add_header 'Access-Control-Allow-Origin' "*";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Methods' 'GET, POST, UPDATE, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
include /etc/nginx/fastcgi_params;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
When I access it directly from my browser, everything is fine, the headers I added are here:
HTTP/1.1 200 OK
Server: nginx/1.4.0
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.3.10-1ubuntu3.6
Set-Cookie: laravel_session=7o4v2fiu460q9p9h2hfo9lpnv6; expires=Mon, 27-May-2013 17:03:02 GMT; path=/
Cache-Control: no-cache
Date: Mon, 27 May 2013 15:03:02 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
Access-Control-Allow-Methods: GET, POST, UPDATE, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since
Content-Length: 0
Content-Type: text/plain charset=UTF-8
Access-Control-Allow-Headers: Authorization
Content-Encoding: gzip
But, when I access it from my app, which is on another domain (angularJS app), the headers don't appear!
Connection:keep-alive
Content-Type:text/html
Date:Mon, 27 May 2013 15:03:12 GMT
Server:nginx/1.4.0
Set-Cookie:laravel_session=k9bastale5kuo0afndbp261025; expires=Mon, 27-May-2013 17:03:12 GMT; path=/; HttpOnly
Transfer-Encoding:chunked
X-Powered-By:PHP/5.3.10-1ubuntu3.6
And then, I have an error :
OPTIONS apibackend 500 (Internal Server Error) angular.min.js:99
OPTIONS apibackend Origin angularapp is not allowed by Access-Control-Allow-Origin. angular.min.js:99
XMLHttpRequest cannot load apibackend. Origin angularapp is not allowed by Access-Control-Allow-Origin.
I have been trying all around, but no clue left.
Thanks for your help!
Upvotes: 4
Views: 4924
Reputation: 307
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
Example, with the CORS handling:
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;
}
Upvotes: 2