web-dev-qa-db-fra.com

nginx add_header ne fonctionne pas

J'ai un problème intriguant dans lequel chaque fois que j'utilise add_header dans la configuration de mon hôte virtuel sur un serveur Ubuntu exécutant nginx avec PHP et php-fpm, cela ne fonctionne tout simplement pas et je n'ai aucune idée de ce que je fais mal. Voici mon fichier de configuration:

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

J'ai essayé d'ajouter des en-têtes aux autres sections d'emplacement, mais le résultat est identique.

Toute aide appréciée !!

44
Petar Vasilev

Il y avait deux problèmes pour moi.

La première est que nginx ne traite que le lastadd_header et qu’il repère un arbre. Ainsi, si vous avez un add_header dans le contexte server, puis un autre dans le contexte imbriqué location, il ne traitera que la directive add_header dans le contexte location. Seul le contexte le plus profond.

À partir de la documentation NGINX sur add_header :

Il pourrait y avoir plusieurs directives add_header. Ces directives sont héritées du niveau précédent si et seulement si aucune directive add_header n'est définie au niveau actuel. 

Le deuxième problème était que le bloc location / {} que j'avais mis en place envoyait réellement nginx à l'autre bloc location ~* (\.php)$ (car il repèrerait toutes les demandes par le biais de index.php, ce qui obligerait nginx à traiter ce bloc php. Ainsi, mes directives add_header à l'intérieur de la première directive d'emplacement étaient inutiles, et cela a commencé à fonctionner après avoir mis toutes les directives dont j'avais besoin dans la directive d'emplacement php.

Enfin, voici ma configuration de travail pour autoriser CORS dans le contexte d’un framework MVC appelé Laravel (vous pouvez le modifier facilement pour s’adapter à tout framework PHP disposant de index.php comme point d’entrée unique pour toutes les demandes).

 serveur {
 root /path/to/app/public;
 index index.php; 

 nom_serveur test.dev; 

 # redirection vers index.php 
 emplacement/{
 try_files $ uri $ uri//index.php?$query_string;
 } 

 # transmettez les scripts PHP au serveur FastCGI à l'écoute de 127.0.0.1:9000
 emplacement ~\.php $ {
 fastcgi_split_path_info ^ (. + \. php) (/.+) $; 
 # NOTE: Vous devriez avoir "cgi.fix_pathinfo = 0;" dans php.ini 

 # Avec php5-fpm: 
 fastcgi_pass unix: /var/run/php5-fpm.sock; 
 fastcgi_index index.php; 
 include fastcgi_params; 

 # configuration cors 
 # liste blanche des domaines autorisés, via une expression régulière 
 # if ($ http_Origin ~ * (http: // localhost (: [0-9] +)?))) {
 if ($ http_Origin ~ *. *) {# ouais, pour le développement local. adaptez votre regex au besoin 
 set $ cors "true"; 
 } 

 # apparemment, les trois instructions if suivantes créent un drapeau pour les "conditions composées" 
 if ($ request_method = OPTIONS) {
 set $ cors "$ {cors} options"; 
 } 

 if ($ request_method = GET) {
 set $ cors "$ {cors} get"; 
 } 

 if ($ request_method = POST) {
 set $ cors "$ {cors} post"; 
 } 

 # traite maintenant le drapeau 
 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; # valeur de contrôle en amont de cache pendant 20 jours 
 add_header 'Méthodes d'accès-contrôle-autoriser-' 'GET, POST, OPTIONS'; 
 add_header Autorisation 'Access-Control-Allow-Headers' ', type de contenu, accepter, origine, agent utilisateur, DNT, contrôle du cache, X-Mx-ReqToken, persistance, demande X avec, si modifiée -Puisque';

 add_header 'Content-Length' 0; 
 add_header 'Content-Type' 'text/plain charset = UTF-8'; 
 retournez 204; 
 } 
 } 

 error_log /var/log/nginx/test.dev.error.log;
 access_log /var/log/nginx/test.dev.access.log;
Buch

L'essentiel pour ce qui précède est à: https://Gist.github.com/adityamenon/6753574

78
Aditya M P

Lorsque je teste les paramètres add_header ci-dessus avec:

# nginx -t && service nginx reload

Je reçois

nginx: [emerg] directive "add_header" is not terminated by ";" in
/etc/nginx/enabled-sites/example.com.conf:21

nginx: configuration file /etc/nginx/nginx.conf test failed

La plainte concerne donc cette ligne:

add_header PS 1

manque le point-virgule (;)

Pour tester les en-têtes que j'aime utiliser

# curl -I http://example.com

Selon le ngx_http_headers_module manual

syntax: add_header name value;
default:     —
context:    http, server, location, if in location

J'ai encore essayé

add_header X-test-A 1;
add_header "X-test-B" "2";
add_header 'X-test-C' '3';

dans le contexte de http, server et location, mais cela n'apparaît que dans le contexte server.

23
birgire

J'avais le problème de ne pas obtenir l'en-tête de réponse car le code de réponse ne se situait pas dans la plage autorisée, sauf si vous spécifiez le mot clé "always" après la valeur de l'en-tête.

D'après les documents officiels:

Ajoute le champ spécifié à un en-tête de réponse à condition que le code de réponse soit égal à 200, 201, 204, 206, 301, 302, 303, 304, 307 ou 308. La valeur peut contenir des variables.

11
Didier Breedt

Tout d’abord, laissez-moi vous dire qu’après avoir regardé sur le Web, j’ai trouvé cette réponse partout:

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

Cependant, j'ai décidé de répondre à cette question par une réponse distincte, car je n'ai réussi à faire fonctionner cette solution particulière qu'après une dizaine d'heures supplémentaires à la recherche d'une solution.

Il semble que Nginx ne définisse aucun type MIME de police [correct] par défaut. En suivant ce tuorial j'ai découvert que je pouvais ajouter ce qui suit:

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

À mon fichier etc/nginx/mime.types. Comme indiqué, la solution ci-dessus a ensuite fonctionné. De toute évidence, cette réponse vise à partager les polices, mais il convient de noter que les types MIME peuvent ne pas être définis dans Nginx.

3
DazBaldwin

Il est évident que l'excentricité/gotcha de l'héritage add_header s'applique également à la couche en amont.

J'avais un script pré-autorisant les demandes destinées à un autre service et renvoyais donc tous les en-têtes de l'autre service.

Une fois que j'ai commencé à ajouter une entrée "Access-Control-Allow-Origin" avec ces en-têtes relayés, le navigateur obtiendrait l'entrée et autoriserait la requête.

1
CNSKnight

Que dit votre journal des erreurs nginx?

Savez-vous quelles lignes add_header cassent la configuration? Sinon, commentez-les tous, puis activez-les 1 par 1, en rechargeant nginx pour voir lequel est le problème. Je commencerais par commenter le bloc:

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

Le problème peut être que vous définissez des en-têtes qui ne sont pas pris en charge par le module httpHeaders principal. L'installation de NginxHttpHeadersMoreModule peut être utile.

Essayez également de remplacer les deux lignes add_header dans le location ~* \... par ce qui suit:

add_header Pragma '';
add_header Cache-Control 'public, max-age=31536000'

Y a-t-il une raison pour laquelle vous avez la configuration gzip ici et pas dans votre nginx.conf global?

0
tseven