Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nginx add_header not working

Tags:

nginx

I am having an intriguing problem where whenever I use add_header in my virtual host configuration on an ubuntu server running nginx with PHP and php-fpm it simply doesn't work and I have no idea what I am doing wrong. Here is my config file:

server {     listen   80; ## listen for ipv4; this line is default and implied     #listen   [::]:80 default ipv6only=on; ## listen for ipv6      root /var/www/example.com/webroot/;     index index.html index.htm index.php;      # Make site accessible from http://www.example.com/     server_name www.example.com;      # max request size     client_max_body_size 20m;      # enable gzip compression     gzip             on;     gzip_static      on;     gzip_min_length  1000;     gzip_proxied     expired no-cache no-store private auth;     gzip_types       text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;      add_header 'Access-Control-Allow-Origin' '*';     add_header 'Access-Control-Allow-Credentials' 'true';     add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken';     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';     add_header PS 1      location / {             # First attempt to serve request as file, then             # as directory, then fall back to index.html             try_files $uri $uri/ /index.php?$query_string;             # Uncomment to enable naxsi on this location             # include /etc/nginx/naxsi.rules     }       location ~* \.(css|js|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|$             # 1 year -> 31536000             expires 500s;             access_log off;             log_not_found off;             add_header Pragma public;             add_header Cache-Control "max-age=31536000, public";     }     # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000     location ~ \.php$ {             fastcgi_split_path_info ^(.+\.php)(/.+)$;             # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini              # With php5-cgi alone:             #fastcgi_pass 127.0.0.1:9000;             # With php5-fpm:             fastcgi_pass unix:/var/run/example.sock;             fastcgi_index index.php?$query_string;             include fastcgi_params;              # instead I want to get the value from Origin request header     }      # Deny access to hidden files     location ~ /\. {             deny all;             access_log off;             log_not_found off;     }      error_page 403 /403/; }  server {     listen 80;     server_name example.com;     rewrite     ^ http://www.example.com$request_uri? permanent; } 

I've tried adding the headers to the other location sections but the result is the same.

Any help appreciated!!

like image 675
Petar Vasilev Avatar asked Aug 26 '13 18:08

Petar Vasilev


People also ask

What is add_header in nginx?

Definition of Nginx Add_header. Nginx add_header allows us to define a value and an arbitrary response header is included in the code of the response. The nginx add_header is defined in the configuration file of nginx.

Where do I put headers in nginx?

If you want to apply these headers to specific files, please add the add_header line in location block (Nginx) or Header set line in filesMatch block (Apache).

Where is Nginx config file located?

By default, the configuration file is named nginx. conf and placed in the directory /usr/local/nginx/conf , /etc/nginx , or /usr/local/etc/nginx .


1 Answers

There were two issues for me.

One is that nginx only processes the last add_header it spots down a tree. So if you have an add_header in the server context, then another in the location nested context, it will only process the add_header directive inside the location context. Only the deepest context.

From the NGINX docs on add_header:

There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.

Second issue was that the location / {} block I had in place was actually sending nginx to the other location ~* (\.php)$ block (because it would repath all requests through index.php, and that actually makes nginx process this php block). So, my add_header directives inside the first location directive were useless, and it started working after I put all the directives I needed inside the php location directive.

Finally, here's my working configuration to allow CORS in the context of an MVC framework called Laravel (you could change this easily to fit any PHP framework that has index.php as a single entry point for all requests).

 server {     root /path/to/app/public;     index index.php;      server_name test.dev;      # redirection to index.php     location / {         try_files $uri $uri/ /index.php?$query_string;     }      # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000     location ~ \.php$ {         fastcgi_split_path_info ^(.+\.php)(/.+)$;         # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini          # With php5-fpm:         fastcgi_pass unix:/var/run/php5-fpm.sock;         fastcgi_index index.php;         include fastcgi_params;          # cors configuration         # whitelist of allowed domains, via a regular expression         # if ($http_origin ~* (http://localhost(:[0-9]+)?)) {         if ($http_origin ~* .*) { # yeah, for local development. tailor your regex as needed              set $cors "true";         }          # apparently, the following three if statements create a flag for "compound conditions"         if ($request_method = OPTIONS) {             set $cors "${cors}options";         }          if ($request_method = GET) {             set $cors "${cors}get";         }          if ($request_method = POST) {             set $cors "${cors}post";         }          # now process the flag         if ($cors = 'trueget') {             add_header 'Access-Control-Allow-Origin' "$http_origin";             add_header 'Access-Control-Allow-Credentials' 'true';         }          if ($cors = 'truepost') {             add_header 'Access-Control-Allow-Origin' "$http_origin";             add_header 'Access-Control-Allow-Credentials' 'true';         }          if ($cors = 'trueoptions') {             add_header 'Access-Control-Allow-Origin' "$http_origin";             add_header 'Access-Control-Allow-Credentials' 'true';              add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days             add_header 'Access-Control-Allow-Methods' 'GET, POST, 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';             return 204;         }     }      error_log /var/log/nginx/test.dev.error.log;     access_log /var/log/nginx/test.dev.access.log; } 

The gist for the above is at: https://gist.github.com/adityamenon/6753574

like image 69
Aditya M P Avatar answered Sep 25 '22 06:09

Aditya M P