5 votes

Est-il impossible d'avoir des en-têtes conditionnels dans Nginx ?

J'essaie actuellement de renvoyer uniquement un ensemble d'en-têtes CORS de manière conditionnelle en utilisant Nginx. Au début, cela semblait être une tâche simple, car j'avais déjà cette configuration fonctionnelle :

upstream api-app {
  server unix:/tmp/api-app.sock fail_timeout=0;
}

server {
  listen 80;
  # [other server stuff...]

  # CORS headers added to all ALL responses of this server (needed for all requests)
  more_set_headers 'Access-Control-Allow-Methods: GET,POST,PATCH,PUT,DELETE,OPTIONS';
  more_set_headers 'Access-Control-Allow-Origin: *';
  more_set_headers 'Access-Control-Allow-Credentials: true';
  more_set_headers 'Access-Control-Request-Method: GET,POST,PATCH,PUT,DELETE,OPTIONS';
  more_set_headers 'Access-Control-Request-Headers: Content-Type';
  more_set_headers 'Access-Control-Allow-Headers: Origin,X-Requested-With,Content-Type,Accept,Session-Id,Role-Id,Visitor-Id,X-Window-Location';
  more_set_headers 'Access-Control-Expose-Headers: X-Total-Entries,X-Total-Pages,X-Page,X-Per-Page,X-Folder-Hierarchy';

  location / {
    # For OPTIONS request only return above headers and no content (also allow caching them)
    if ($request_method = 'OPTIONS') {
      # cache above (Access-Control) headers
      add_header 'Access-Control-Max-Age' 600;

      # set content length and type just for good measure:
      add_header 'Content-Length' 0;
      add_header 'Content-Type' 'text/plain charset=UTF-8';

      # return 204 - no content
      return 204;
    }

    # Forward requests to actual app (if all above conditions did not match)
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_read_timeout 35;
    proxy_send_timeout 35;

    proxy_pass http://api-app;
  }
}

Donc je voulais juste changer la section de l'en-tête CORS en s.th. comme ceci

# ...
  set $cors '';

  if ($http_origin ~ '^https?://(some.domain|some.other.domain|other-allows.domain)') {
      set $cors 'true';
  }

  if ($cors = 'true') {
      more_set_headers 'Access-Control-Allow-Methods: GET,POST,PATCH,PUT,DELETE,OPTIONS';
      more_set_headers 'Access-Control-Allow-Origin: $http_origin';
      more_set_headers 'Access-Control-Allow-Credentials: true';
      more_set_headers 'Access-Control-Request-Method: GET,POST,PATCH,PUT,DELETE,OPTIONS';
      more_set_headers 'Access-Control-Request-Headers: Content-Type';
      more_set_headers 'Access-Control-Allow-Headers: Origin,X-Requested-With,Content-Type,Accept,Session-Id,Role-Id,Visitor-Id,X-Window-Location';
      more_set_headers 'Access-Control-Expose-Headers: X-Total-Entries,X-Total-Pages,X-Page,X-Per-Page,X-Folder-Hierarchy';
  }

  location / {
# ...

Cependant nginx -t m'a rapidement dit more_set_headers ne peut pas être utilisé dans une instruction if. Add_header non plus.

J'ai compris que dans le location section, cela fonctionnerait. Mais je savais déjà que ce n'était pas une bonne solution, comme nous le savons tous. si c'est le mal dans les sections de localisation de nginx . Et j'avais raison car les en-têtes CORS seraient perdus pour la requête OPTIONS, pour laquelle j'avais déjà un cas if (un cas OK, car il revient).

J'ai également trouvé l'option d'utiliser Nginxs. fonction cartographique . Mais cela ne fonctionne que si je veux modifier les valeurs des en-têtes, pas si je veux ajouter un bloc entier d'en-têtes.

Ma question est donc la suivante : Existe-t-il un moyen d'ajouter des en-têtes de manière conditionnelle (sans utiliser map) et en dehors du bloc d'emplacement ? L'idéal serait de pouvoir inclure la section CORS afin de pouvoir l'utiliser sur plusieurs serveurs (par exemple, des sites nginx).

4voto

Tero Kilkanen Points 32968

Je ne sais pas si more_set_headers accepte les chaînes vides. S'il l'accepte, vous pouvez alors définir plusieurs map déclarations :

map $http_origin $cors_methods {
    default "";
    ~^https?://(some.domain|some.other.domain|other-allows.domain) Access-Control-Allow-Methods: GET,POST,PATCH,PUT,DELETE,OPTIONS;
}

map $http_origin $cors_origin {
    default "";
    ~^https?://(some.domain|some.other.domain|other-allows.domain) Access-Control-Allow-Origin: $http_origin;
}

Et puis utilise ça :

more_set_headers $cors_methods;
more_set_headers $cors_origin;

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X