添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Stack Exchange Network

Stack Exchange network consists of 182 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers. Visit Stack Exchange

Server Fault is a question and answer site for system and network administrators. It only takes a minute to sign up.

Sign up to join this community

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams I had a similar issue, but to address a maintenance mode with a 503 status, and then the headers were not set (4xx, 5xx statuses). Adding 'always' fixed that: add_header Access-Control-Allow-Origin * always; bfredo123 Nov 6, 2022 at 11:06

Nginx has to be compiled with http://wiki.nginx.org/NginxHttpHeadersModule (default on Ubuntu and some other Linux distros). Then you can do this

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin *;
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;
                Any way to not have to repeat these lines for every location? Can we put it under the server {} block?
– geoyws
                Oct 11, 2015 at 5:05
                @geoyws (without the @ I didnt get a notification); you could put it above location, thats fine :)
– Chris McKee
                Dec 17, 2015 at 15:12
                I would like to add that it is useful to add always option to all add_header so that headers are added also for non-200 responses. Since nginx 1.7.5: nginx.org/en/docs/http/ngx_http_headers_module.html
– Mitar
                Feb 27, 2019 at 18:48

Here is the article that I wrote which avoids some of the duplication for GET|POST. It should get you going with CORS in Nginx.

nginx access control allow origin

Here is the sample snippet from the post:

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 per SF policy you need to copy the information into the post, not just link to it. Websites can disappear at any time, which would be loss of information.
– Tim
                Apr 17, 2017 at 22:07
                Access-Control-Allow-Origin: * does not work with Access-Control-Allow-Credentials: true because for credentials to work origin must be exactly the same as sent in CORS request (not *). See fetch.spec.whatwg.org/#http-cors-protocol
– piotrekkr
                Jul 26, 2021 at 7:18
                @piotrekkr you're looking for  ```         if ($http_origin = ''){             set $http_origin "*";         }          proxy_hide_header Access-Control-Allow-Origin;         add_header Access-Control-Allow-Origin $http_origin; ``` in order to do that.  gist.github.com/ChrisMcKee/f0816222acf0692526d01a7e82b6651d
– Chris McKee
                Jul 27, 2021 at 8:51

In some cases you need to use add_header directives with always to cover all HTTP response codes.

location / {
    add_header 'Access-Control-Allow-Origin' '*' always;

From documentation:

If the always parameter is specified (1.7.5), the header field will be added regardless of the response code.

Adds the specified field to a response header provided that the response code equals 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0). Parameter value can contain variables.

This fixed it for me. 404 caused the header to not be added, which then caused a client's agent to behave strangely. – Climax Aug 6, 2021 at 15:07 This work out for me but I needed to add proxy_hide_header Access-Control-Allow-Origin; before add_header .... I used https://cors-test.codehappy.dev/ to debug it. – Nico Serrano Jul 1, 2022 at 16:01

Firstly, let me say that @hellvinz answer is working for me:

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin *;

However, I have decided to answer this question with a separate answer as I only managed to get this solution working after putting in about ten more hours looking for a solution.

It seems that Nginx doesn't define any (correct) font MIME types by default. By following this tuorial I found I could add the following:

application/x-font-ttf           ttc ttf;
application/x-font-otf           otf;
application/font-woff            woff;
application/font-woff2           woff2;
application/vnd.ms-fontobject    eot;

To my etc/nginx/mime.types file. As stated, the above solution then worked.

I'd usually point people to check the mime type file on H5BP github.com/h5bp/server-configs-nginx/blob/master/mime.types :) – Chris McKee Jan 11, 2017 at 17:06 this didnt fix my issue. I did the change in mime.type file and also in the nginx.conf file inside /etc/nginx – Suraj Jeswara Jul 8, 2020 at 4:56

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.

sudo apt-get install nginx-extras

Then use more_set_headers in the nginx.conf file, i have pasted my sample below

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;

In my case adding the Access Control with a wildcard header didn't work. I ended up having to set the proxy header with my web apps host and Access Control header with the origin set. Here's an example that worked for me:

location /service {
    proxy_pass http://graphql-server:8080;
    proxy_set_header Origin http://graphql-server:8080;
    proxy_hide_header Access-Control-Allow-Origin;
    add_header Access-Control-Allow-Origin "$http_origin" always;

In my case, using Rails 5, the only working solution has been adding the rack-cors gem. Like so:

in /Gemfile

# Gemfile
gem 'rack-cors'

in config/initializers/cors.rb

# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'localhost:4200'
    resource '*',
      headers: :any,
      methods: %i(get post put patch delete options head)

source: https://til.hashrocket.com/posts/4d7f12b213-rails-5-api-and-cors

I was using nginx as a reverse proxy to serve the rails 5 app. This is a particular case where the CORS restriction was not coming from nginx but from the origin Rails App behind it. – user9869932 Oct 3, 2018 at 10:39