Ostatnie wyjaśnienie, gdy sam natknąłem się na ten problem: nginx.org/en/docs/http/request_processing.html wyraźnie stwierdza: „Pamiętaj, że lokalizacje wszystkich typów testują tylko część URI wiersza żądania bez argumentów. Dzieje się tak, ponieważ argumenty w ciągu zapytania można podać na kilka sposobów ”
Thomas Urban
Odpowiedzi:
37
Czy bloki lokalizacji nginx mogą pasować do ciągu zapytania adresu URL?
Krótka odpowiedź : nie
Długa odpowiedź : istnieje obejście, jeśli mamy tylko kilka takich bloków lokalizacji.
Oto przykładowe obejście dla 3 bloków lokalizacji, które muszą pasować do określonych ciągów zapytań:
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
}
}
Możesz użyć $ query_string, $ args lub $ arg_fieldname. Wszyscy wykonają robotę. Możesz dowiedzieć się więcej o error_page w oficjalnych dokumentach .
Ciekawe podejście! Czy mogę polecić $args ~ "service=git-send-pack"zamiast $args = "service=git-send-pack"? Ten formularz obsługuje wiele parametrów zapytania.
Derek Mahar
1
stackoverflow.com/a/40313590/107158 ilustruje podejście, które zastosowałem do obsługi argumentów ciągu zapytania. Podobnie jak twoja odpowiedź, moje używa ifi $arg_fieldname, ale używa rewritezamiast error_pagei location @name. Zauważ, że w tym przykładzie, moje próby używając @namedo zastępczego parametru rewritebyły nieudane.
Derek Mahar
1
Nawiasem mówiąc, powinno być $args ~i $arg_somerandomfield =.
Derek Mahar
1
W maptym celu można również użyć funkcji nginx , która jest szybsza.
Tero Kilkanen
1
@PothiKalimuthu, dzięki za wyjaśnienie tego. Tymczasem zrobiłem tymczasem zastąpienie queryparametru ścieżką URL taką jak ta feedback/{auth_key}zamiast /feedback?auth_key=abc. W ten sposób nie muszę używać if, mogę zdefiniować wzór lokalizacji za pomocą regexi to wszystko.
WM
4
Wiem, że to pytanie ma ponad rok, ale ostatnie kilka dni spędziłem na niszczeniu mózgu przez podobny problem. Chciałem różnych zasad uwierzytelniania i obsługi publicznych i prywatnych repozytoriów, w tym wypychania i wyciągania. To w końcu wymyśliłem, więc pomyślałem, że podzielę się. Wiem, że ifjest to trudna dyrektywa, ale wydaje mi się, że to działa dobrze:
# 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;
# ...
}
?
)?Odpowiedzi:
Krótka odpowiedź : nie
Długa odpowiedź : istnieje obejście, jeśli mamy tylko kilka takich bloków lokalizacji.
Oto przykładowe obejście dla 3 bloków lokalizacji, które muszą pasować do określonych ciągów zapytań:
Możesz użyć $ query_string, $ args lub $ arg_fieldname. Wszyscy wykonają robotę. Możesz dowiedzieć się więcej o error_page w oficjalnych dokumentach .
Ostrzeżenie: nie używaj standardowych kodów HTTP .
źródło
$args ~ "service=git-send-pack"
zamiast$args = "service=git-send-pack"
? Ten formularz obsługuje wiele parametrów zapytania.if
i$arg_fieldname
, ale używarewrite
zamiasterror_page
ilocation @name
. Zauważ, że w tym przykładzie, moje próby używając@name
do zastępczego parametrurewrite
były nieudane.$args ~
i$arg_somerandomfield =
.map
tym celu można również użyć funkcji nginx , która jest szybsza.query
parametru ścieżką URL taką jak tafeedback/{auth_key}
zamiast/feedback?auth_key=abc
. W ten sposób nie muszę używaćif
, mogę zdefiniować wzór lokalizacji za pomocąregex
i to wszystko.Wiem, że to pytanie ma ponad rok, ale ostatnie kilka dni spędziłem na niszczeniu mózgu przez podobny problem. Chciałem różnych zasad uwierzytelniania i obsługi publicznych i prywatnych repozytoriów, w tym wypychania i wyciągania. To w końcu wymyśliłem, więc pomyślałem, że podzielę się. Wiem, że
if
jest to trudna dyrektywa, ale wydaje mi się, że to działa dobrze:źródło