Une dernière clarification alors que je suis moi-même tombé sur ce problème: nginx.org/en/docs/http/request_processing.html indique clairement: "Notez que les emplacements de tous types testent uniquement une partie URI de la ligne de demande sans arguments. Ceci est fait parce que les arguments dans la chaîne de requête peut être donnée de plusieurs façons "
Thomas Urban
Réponses:
37
Les blocs d'emplacement nginx peuvent-ils correspondre à une chaîne de requête URL?
Réponse courte : Non.
Réponse longue : il existe une solution de contournement si nous n'avons qu'une poignée de ces blocs de localisation.
Voici un exemple de solution de contournement pour 3 blocs d'emplacement qui doivent correspondre à des chaînes de requête spécifiques:
server {
#... common definitions such as server, root
location / {
error_page 418 = @queryone;
error_page 419 = @querytwo;
error_page 420 = @querythree;
if ( $query_string = "service=git-receive-pack" ) { return 418; }
if ( $args ~ "service=git-upload-pack" ) { return 419; }
if ( $arg_somerandomfield = "somerandomvaluetomatch" ) { return 420; }
# do the remaining stuff
# ex: try_files $uri =404;
}
location @queryone {
# do stuff when queryone matches
}
location @querytwo {
# do stuff when querytwo matches
}
location @querythree {
# do stuff when querythree matches
}
}
Vous pouvez utiliser $ query_string, $ args ou $ arg_fieldname. Tous feront l'affaire. Vous pouvez en savoir plus sur error_page dans les documents officiels .
Approche intéressante! Puis-je recommander à la $args ~ "service=git-send-pack"place de $args = "service=git-send-pack"? Ce formulaire contient plusieurs paramètres de requête.
Derek Mahar
1
stackoverflow.com/a/40313590/107158 illustre l'approche que j'ai suivie pour gérer les arguments de chaîne de requête. Comme votre réponse, la mienne utilise ifet $arg_fieldname, mais utilise à la rewriteplace de error_pageet location @name. Notez que dans cet exemple, mes tentatives d'utilisation @namedu paramètre de remplacement dans rewriteont échoué.
Derek Mahar
1
Au fait, ça devrait être $args ~et $arg_somerandomfield =.
Derek Mahar
1
On peut également utiliser la mapfonction nginx à cette fin, ce qui est plus rapide.
Tero Kilkanen du
1
@PothiKalimuthu, merci d'avoir clarifié cela. Ce que j'ai fait en attendant, c'est de remplacer le queryparamètre par un chemin d'URL comme celui-ci feedback/{auth_key}au lieu de /feedback?auth_key=abc. De cette façon, je n'ai pas besoin d'utiliser if, je peux définir un modèle d'emplacement à l'aide de regexet c'est tout.
WM
4
Je sais que cette question remonte à plus d'un an, mais j'ai passé les derniers jours à détruire mon cerveau pour un problème similaire. Je voulais des règles d'authentification et de gestion différentes pour les dépôts publics et privés, y compris pour pousser et tirer. C'est ce que j'ai finalement trouvé, alors j'ai pensé que je partagerais. Je sais que ifc'est une directive délicate, mais cela semble très bien fonctionner pour moi:
# pattern for all repos, public or private, followed by username and reponame
location ~ ^(?:\/(private))?\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?$ {
# if this is a pull request
if ( $arg_service = "git-upload-pack" ) {
# rewrite url with a prefix
rewrite ^ /upload$uri;
}
# if this is a push request
if ( $arg_service = "git-receive-pack" ) {
# rewrite url with a prefix
rewrite ^ /receive$uri;
}
}
# for pulling public repos
location ~ ^\/upload(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {
# auth_basic "git";
# ^ if you want
# ...
# fastcgi_pass unix:/var/run/fcgiwrap.socket;
# ...
}
# for pushing public repos
location ~ ^\/receive(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {
# auth_basic "git";
# ^ if you want
# ...
# fastcgi_pass unix:/var/run/fcgiwrap.socket;
# ...
}
# for pulling private repos
location ~ ^\/upload\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {
# auth_basic "git";
# ^ if you want
# ...
# fastcgi_pass unix:/var/run/fcgiwrap.socket;
# ...
}
# for pushing private repos
location ~ ^\/receive\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {
# auth_basic "git";
# ^ if you want
# ...
# fastcgi_pass unix:/var/run/fcgiwrap.socket;
# ...
}
?
)?Réponses:
Réponse courte : Non.
Réponse longue : il existe une solution de contournement si nous n'avons qu'une poignée de ces blocs de localisation.
Voici un exemple de solution de contournement pour 3 blocs d'emplacement qui doivent correspondre à des chaînes de requête spécifiques:
Vous pouvez utiliser $ query_string, $ args ou $ arg_fieldname. Tous feront l'affaire. Vous pouvez en savoir plus sur error_page dans les documents officiels .
Avertissement: veillez à ne pas utiliser les codes HTTP standard .
la source
$args ~ "service=git-send-pack"
place de$args = "service=git-send-pack"
? Ce formulaire contient plusieurs paramètres de requête.if
et$arg_fieldname
, mais utilise à larewrite
place deerror_page
etlocation @name
. Notez que dans cet exemple, mes tentatives d'utilisation@name
du paramètre de remplacement dansrewrite
ont échoué.$args ~
et$arg_somerandomfield =
.map
fonction nginx à cette fin, ce qui est plus rapide.query
paramètre par un chemin d'URL comme celui-cifeedback/{auth_key}
au lieu de/feedback?auth_key=abc
. De cette façon, je n'ai pas besoin d'utiliserif
, je peux définir un modèle d'emplacement à l'aide deregex
et c'est tout.Je sais que cette question remonte à plus d'un an, mais j'ai passé les derniers jours à détruire mon cerveau pour un problème similaire. Je voulais des règles d'authentification et de gestion différentes pour les dépôts publics et privés, y compris pour pousser et tirer. C'est ce que j'ai finalement trouvé, alors j'ai pensé que je partagerais. Je sais que
if
c'est une directive délicate, mais cela semble très bien fonctionner pour moi:la source