nginx - Nginx If语句在位置之前执行?
问题描述
我很困惑为什么 nginx 在 location 语句“之前”执行我的 If 语句。更准确的说,为什么nginx不执行return语句然后停止处理?
即使 $http_x_forwarded_host 不是www.acme.com因为 if 语句位于 location 语句的下方,我希望如果我打开 /xyz 会得到带有“hello world”的 200。但是 nginx 只是忽略了 location 语句,并遇到了 if 子句。有任何想法吗?我试过break;
没有运气。
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.html index.htm index.php;
location /xyz {
return 200 'hello world';
}
if ($http_x_forwarded_host != "www.acme.com") {
return 301 https://www.acme.com$uri;
}
}
解决方案
你是对的,来自 的所有指令都是在位置选择机制取代它之前ngx_http_rewrite_module
执行的。使用指令意味着从重写模块中断这些指令的执行,并立即根据最佳匹配位置强制执行请求。发生这种情况是因为尽管 nginx 配置通常是声明性的,但 rewrite 模块命令式地评估其指令。这对于每个 nginx 新手来说总是一个困惑的根源。您可以在此处阅读有关重写模块内部实现的更多信息。break
话虽如此,您无法通过配置实现这种行为。这并不意味着您根本无法实现您想要的,一种可能的解决方案是使用正则表达式负前瞻功能:
if ($http_x_forwarded_host != "www.acme.com") {
# do the redirect only if the URI doesn't start with '/xyz'
rewrite ^(?!/xyz) https://www.acme.com$uri permanent;
}
location /xyz {
return 200 'hello world';
}
如果你想做一些复杂的请求处理而不是重定向,你可以使用一个internal
位置:
if ($http_x_forwarded_host != "www.acme.com") {
# in case you will need an original URI later, you can save its value
# set $original_uri $uri;
# process the request with the special location only if the URI doesn't start with '/xyz'
rewrite ^(?!/xyz) /special;
}
location /xyz {
return 200 'hello world';
}
location /special {
internal;
... # any custom processing here, for example 'return 403;'
}
很明显,对于这样的位置,您应该选择一个不会以任何方式干扰您现有站点的 URI 前缀。
推荐阅读
- javascript - TensorFlow.js PoseNet 模型关键点动画
- javascript - 使用 Cypress 处理 Windows 确认弹出窗口
- sql - 如何从多个表中选择公共元素?
- java - 如何用java编写xls文件?
- python - 从字符串中识别和提取日期 - Python
- google-apps-script - 谷歌脚本自定义触发器 onEdit(e) 问题
- azure-devops - 使用托管服务帐户安装自托管代理?
- java - 为 FileOutputStream 方法调用 System.loadLibrary()
- javascript - 使用 vuex 处理 vue/axios 中的全局 http 响应错误
- apache - PHP-SSLCURL 错误 - 无法加载客户端证书:-8018 (SEC_ERROR_UNKNOWN_PKCS11_ERROR)