Deb*_*pta 4 nginx nginx-reverse-proxy nginx-config
我需要根据 http 请求来源路由流量。我有两个环境,我们需要使用“$http_referer”将“/us-en”的每个http请求重定向到Environment1,其他人重定向到Environment2。
location ~ /us-en {
proxy_pass Environment1;
proxy_set_header Host Environment1;
}
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
注意:默认情况下,所有流量都进入 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
}
}
Run Code Online (Sandbox Code Playgroud)
使用这样的配置请求your_domain.com/home/path/filefrom dev.xyz.com/home/...(但不是 from 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
}
}
Run Code Online (Sandbox Code Playgroud)
更新@2020.11.11
除了这个答案以某种方式获得了 5 分之外,给定的解决方案的设计非常糟糕(location在嵌套if块和嵌套块中使用不同的内容处理程序不是一个好方法;此外,具有一个if块除了来自如果可能,应该避免使用nginx重写模块)并且在早期的 nginx 版本上根本不起作用(当我看到我的一些早期答案时,我想哭)。一个原始的 OP 问题是
逻辑应该如下所示,但有一些语法错误。
Run Code Online (Sandbox Code Playgroud)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
}
Run Code Online (Sandbox Code Playgroud)
如果不代理传递意味着在本地为请求提供服务,则解决方案更复杂:
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;
...
}
Run Code Online (Sandbox Code Playgroud)
该try_files /dev/null @the_named_location;诀窍是取自这个出色答卷。
然而,现在编辑过的 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;
}
Run Code Online (Sandbox Code Playgroud)