Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable CORS in Nginx proxy server?

As my title, here is the config file located in conf.d/api-server.conf

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-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;   } } 

The nginx.conf file stay the same as default.

After I send request to api.localhost (api.localhost/admin/login), I still receive 405 error:

XMLHttpRequest cannot load http://api.localhost/admin/login. Response  to preflight request doesn't pass access control check: No 'Access- Control-Allow-Origin' header is present on the requested resource.  Origin 'http://admin.localhost:3000' is therefore not allowed access.  The response had HTTP status code 405. 

That is the response from server That's the request looks like

like image 285
qwang07 Avatar asked Aug 31 '17 16:08

qwang07


People also ask

Does NGINX support CORS?

To enable CORS on NGINX, you need to use the add_header directive and add it to the appropriate NGINX configuration file. to allow access from any domain.

What is CORS NGINX?

CORS, also known as cross origin resource sharing is a technique used in modern web browsers that controls access to resources hosted in a web server. CORS uses additional headers such as origin, access-control-origin, and many more to determine whether the requested resource has permission to be sent to the browser.


1 Answers

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

like image 200
Tarun Lalwani Avatar answered Sep 28 '22 09:09

Tarun Lalwani