簡體   English   中英

基於 referer 的 nginx 條件路由

[英]conditional routing with nginx based on referer

我需要根據 http 請求來源路由流量。 我有兩個環境,我們需要使用“$http_referer”將“/us-en”的每個 http 請求重定向到 Environment1,將其他請求重定向到 Environment2。

  1. 基於位置的重定向有效。
location ~ /us-en { 
    proxy_pass Environment1; 
    proxy_set_header Host Environment1; 
} 
  1. 對於“$http_referer”,以下選項不起作用。 請求你的建議。
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM