How do I set the Access-Control-Allow-Origin header so I can use web-fonts from my subdomain on my main domain?
Notes:
You'll find examples of this and other headers for most HTTP servers in the HTML5BP Server Configs projects https://github.com/h5bp/server-configs
9 Answers 9
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 *;
}
-
11That module seems to be compiled by default (at least on Ubuntu).Steve Bennett– Steve Bennett2014年09月08日 13:25:05 +00:00Commented Sep 8, 2014 at 13:25
-
2also compiled by default on amazon linux repoRoss– Ross2015年09月01日 21:16:18 +00:00Commented Sep 1, 2015 at 21:16
-
2In which file and location we should put this location directive ?Sumit Arora– Sumit Arora2017年01月17日 14:11:27 +00:00Commented Jan 17, 2017 at 14:11
-
2It doesn't work for me. Nginx 1.10.0, Ubuntu 16.04Omid Amraei– Omid Amraei2017年06月17日 07:04:41 +00:00Commented Jun 17, 2017 at 7:04
-
1@SumitArora in
/etc/nginx/conf.d/default.confI guess ...0xC0DEGURU– 0xC0DEGURU2021年03月11日 19:34:15 +00:00Commented Mar 11, 2021 at 19:34
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;
-
1Any way to not have to repeat these lines for every location? Can we put it under the server {} block?geoyws– geoyws2015年10月11日 05:05:25 +00:00Commented Oct 11, 2015 at 5:05
-
@geoyws (without the @ I didnt get a notification); you could put it above location, thats fine :)Chris McKee– Chris McKee2015年12月17日 15:12:45 +00:00Commented Dec 17, 2015 at 15:12
-
access-control-expose-headers is missing herechovy– chovy2015年12月23日 19:45:58 +00:00Commented Dec 23, 2015 at 19:45
-
9Please avoid using
ifin nginx - even the official manual discourages it.aggregate1166877– aggregate11668772018年05月22日 10:43:11 +00:00Commented May 22, 2018 at 10:43 -
7I would like to add that it is useful to add
alwaysoption to alladd_headerso that headers are added also for non-200 responses. Since nginx 1.7.5: nginx.org/en/docs/http/ngx_http_headers_module.htmlMitar– Mitar2019年02月27日 18:48:55 +00:00Commented 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 / {
# 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;
}
if ($request_method ~* '(GET|POST)') {
add_header 'Access-Control-Allow-Origin' '*';
}
# Handle request
# ...
}
}
-
4As 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– Tim2017年04月17日 22:07:12 +00:00Commented Apr 17, 2017 at 22:07
-
3Valid point @tim, updated to include the codegansbrest– gansbrest2017年04月17日 22:58:19 +00:00Commented Apr 17, 2017 at 22:58
-
3Consider using status code
204 No contentas it seems more appropriate.Slava Fomin II– Slava Fomin II2019年01月21日 11:00:26 +00:00Commented Jan 21, 2019 at 11:00 -
Access-Control-Allow-Origin: *does not work withAccess-Control-Allow-Credentials: truebecause for credentials to work origin must be exactly the same as sent in CORS request (not*). See fetch.spec.whatwg.org/#http-cors-protocolpiotrekkr– piotrekkr2021年07月26日 07:18:00 +00:00Commented 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/f0816222acf0692526d01a7e82b6651dChris McKee– Chris McKee2021年07月27日 08:51:18 +00:00Commented 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– Climax2021年08月06日 15:07:58 +00:00Commented Aug 6, 2021 at 15:07
-
This work out for me but I needed to add
proxy_hide_header Access-Control-Allow-Origin;beforeadd_header .... I used https://cors-test.codehappy.dev/ to debug it.Nico Serrano– Nico Serrano2022年07月01日 16:01:23 +00:00Commented 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.
-
2I'd usually point people to check the mime type file on H5BP github.com/h5bp/server-configs-nginx/blob/master/mime.types :)Chris McKee– Chris McKee2017年01月11日 17:06:52 +00:00Commented 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/nginxSuraj Jeswara– Suraj Jeswara2020年07月08日 04:56:28 +00:00Commented 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;
}
}
-
-
OMG, many thanks. You just saved me! 3 hours looking for a solutionInfobuscador– Infobuscador2022年04月12日 13:16:16 +00:00Commented Apr 12, 2022 at 13:16
-
You can add 'always' at the end of the the add_header directive - see nginx.org/en/docs/http/ngx_http_headers_module.htmlcrowne– crowne2024年07月05日 14:42:42 +00:00Commented Jul 5, 2024 at 14:42
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)
end
end
source: https://til.hashrocket.com/posts/4d7f12b213-rails-5-api-and-cors
-
how does that help nginx serve static files?Walf– Walf2018年10月03日 04:52:59 +00:00Commented Oct 3, 2018 at 4:52
-
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– user98699322018年10月03日 10:39:50 +00:00Commented Oct 3, 2018 at 10:39
I spent the last few days banging my head against the wall trying to resolve this issue, but could never get it to work.
Reason: I was loading the nginx website in a jQuery div tag. I am going to assume this is not allowed for CORS.
Solution: Load the nginx page in an IFRAME.
<iframe
src="https://stream.website.com:9443/Radio.html"
title="Your Channel"></iframe>
Using this method, there is no need for CORS code in your site-enabled/website.
I hope this will help someone, as it sure made my morning when I decided to use it.
add_header Access-Control-Allow-Origin * always;