2 votes

Les variables $sent_http_ disparaissent dans Nginx dans certaines circonstances

Je rencontre un problème étrange avec Nginx. Voici une configuration minimale qui reproduit l'erreur :

server {
    server_name     mydomain.com;
    listen          111.111.111.111:80;
    root            /some/path;

    set     $some_var   $sent_http_content_type;
    add_header  "X-Debug" $sent_http_content_type;
}

Dans ce cas X-Debug n'est jamais affiché dans la réponse. Mais, si je commente cette ligne :

set     $some_var   $sent_http_content_type;

tout fonctionne. Cela me semble très étrange, car cette ligne ne réaffecte pas le fichier $sent_http_content_type var, mais ne fait que lire.

On dirait qu'il appartient à $sent_http_ variables uniquement.

J'ai aussi essayé "${sent_http_content_type}" au lieu de $sent_http_content_type avec le même résultat.

more_set_headers ne résout pas ce problème.

Pourquoi Nginx se comporte-t-il ainsi ? S'agit-il d'un bogue ?

Edit :
L'exemple que j'ai fourni est juste le cas le plus simple où $sent_http_ les vars disparaissent. En fait, je veux faire quelque chose comme ça :

if ($sent_http_access_control_allow_origin ~ "^(https?)://([^/]+)") {
    set $new_cors http://$1.$2.proxy.mydomain.com;
}
more_set_headers "Access-Control-Allow-Origin: $new_cors";

J'écris un serveur proxy et je dois remplacer Access-Control-Allow-Origin car sinon les sites mandataires ne fonctionnent pas comme prévu.

Dans l'exemple ci-dessus if (en server ) ne donne jamais true même si un tel en-tête existe et qu'il correspond à mon expression régulière.

Peut-on y remédier ? Nous apprécions votre aide !

0 votes

if a également été exécutée trop tôt pour vous.

0 votes

@AlexeyTen, cela signifie-t-il qu'il est impossible de remplacer l'en-tête de réponse par une expression rationnelle ?

0 votes

C'est possible. Je vais modifier la réponse

2voto

Alexey Ten Points 7572

Nginx rewrite (où les variables et les set appartient) est assez peu intuitif et fragile. Mais, en fait

set     $some_var   $sent_http_content_type;

n'a pas de sens de toute façon parce que set est exécutée au début de la requête et il n'y a pas de directive $sent_http_* variables disponibles pour le moment.

Ce que vous pourriez faire (si vous voulez vraiment utiliser $sent_http_* d'une manière ou d'une autre) est d'utiliser map directive.

map $sent_http_content_type $some_var {
    default $sent_http_content_type;
}

...
server {
    ...
    add_header "X-Debug"  $sent_http_content_type;
    add_header "X-Debug2" $some_var;
}

EDIT : Votre problème pourrait être résolu avec un peu plus de map mais ce serait beaucoup plus facile si vous pouviez utiliser le module Lua.

Voici comment on pourrait le faire avec map s : (assez illisible et non maintenable)

map $sent_http_access_control_allow_origin $__proto {
    default "NONE";
    "~^(?<_>https?):" "$_";
}

map $sent_http_access_control_allow_origin $__host {
    default "";
    "~^https?://(?<_>[^/]+)" "$_";
}

map "http://$__proto.$__host.proxy.mydomain.com" $new_cors {
    default "";
    "~^http://NONE" "";
    "~^(?<_>.+)$" "$_";
}

0 votes

+1 Merci pour l'explication ! Cependant map ne résout pas mon vrai problème. Veuillez voir mon édition. Est-il possible d'obtenir ce que je veux ? J'apprécie votre aide.

0 votes

Votre dernière map La solution est un peu tordue mais elle fait le travail . Merci encore, @AlexeyTen !

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