[英]conditional routing with nginx based on referer
我需要根據 http 請求來源路由流量。 我有兩個環境,我們需要使用“$http_referer”將“/us-en”的每個 http 請求重定向到 Environment1,將其他請求重定向到 Environment2。
location ~ /us-en {
proxy_pass Environment1;
proxy_set_header Host Environment1;
}
if ($http_referer ~ ^https?://dev.xyz.com/us-en){
rewrite ^/us-en(/*)$ HOME_PAGE$1 break;
proxy_pass Environment1;
}
Error: nginx: [emerg] "proxy_pass" directive is not allowed here in /opt/nginx/conf/nginx.conf.
注意:默認情況下,所有流量都進入 Environment2,因為存在上游配置。
# needed if your proxy destination specified with domain name instead of IP address
resolver 8.8.8.8;
location /home/ {
proxy_set_header Host HOST1;
# setup other proxied headers if needed
if ($http_referer ~ ^https?://dev.xyz.com/home) {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_pass https://HOST1:8080; # this can be specified by IP address
}
}
通過這樣的配置請求,從dev.xyz.com/home/...
向your_domain.com/home/path/file
請求(但不是從dev.xyz.com/any/other/path
!)將被代理到https://HOST1:8080/HOME_PAGE/path/file
。 如果您使用域名而不是 IP 地址指定代理目的地,則需要在服務器配置中指定附加參數resolver
。 如果您有本地名稱服務器,則可以使用本地名稱服務器,或者使用外部服務器,例如 Google 公共 DNS (8.8.8.8) 或您的 ISP 為您提供的 DNS。 無論如何,這樣的配置會導致額外的 DNS 查找,所以如果可以的話,請使用 IP 地址指定代理目的地。
更新
還有另一種方法可以使用valid_referers
指令:
# needed if your proxy destination specified with domain name instead of IP address
resolver 8.8.8.8;
location /home/ {
proxy_set_header Host HOST1;
# setup other proxied headers if needed
valid_referers example.com/home;
if ($invalid_referer = "") {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_pass https://HOST1:8080; # this can be specified by IP address
}
}
更新@2020.11.11
除了這個答案以某種方式獲得了 5 分之外,給定的解決方案的設計非常糟糕(在location
和嵌套的if
塊中使用不同的內容處理程序不是一個好方法;此外,有一個if
塊與其他任何指令如果可能的話,應該避免使用 nginx重寫模塊)並且在早期的 nginx 版本上根本不起作用(當我看到我的一些早期答案時我想哭)。 一個原始的 OP 問題是
邏輯應該如下所示,但有一些語法錯誤。
if ($http_origin ~ '^http?://(dev.xyz.com/home)') { set $flag 'true'; } if ($flag = 'true') { location /home/ { proxy_pass "https://HOST1:8080/HOME PAGE/"; } }else{ Do Not proxy pass }
目前還不清楚不代理通過是什么意思。 如果它意味着返回一些 HTTP 錯誤(例如,HTTP 403 Forbidden),可以通過以下配置來完成:
location /home/ {
if ($http_referer !~ ^https?://dev.xyz.com/home) {
return 403;
}
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_set_header Host HOST1;
# setup other proxied headers if needed
proxy_pass https://HOST1:8080; # this can be specified by IP address
}
如果不代理傳遞意味着在本地服務請求,解決方案更復雜:
map $http_referer $loc {
~^https?://dev.xyz.com/home loc_proxy;
default loc_local;
}
server {
...
location /home/ {
try_files /dev/null @$loc;
}
location @loc_proxy {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_set_header Host HOST1;
# setup other proxied headers if needed
proxy_pass https://HOST1:8080;
}
location @loc_local {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
root /path/to/required/page;
...
}
try_files /dev/null @the_named_location;
技巧取自this excellent answer。
但是現在編輯過的 OP 的問題說明了不同的要求,這也可以通過map
指令幫助來實現:
map $http_referer $environment {
~^https?://dev.xyz.com/home Environment1;
default Environment2;
}
server {
...
location /home/ {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_set_header Host $environment;
# setup other proxied headers if needed
proxy_pass https://$environment;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.