存疑地方:location 处只要使用了精准匹配(=),就直接查找本地资源,而不会进行代理调用,这个地方一直没找到答案。
#报错
192.168.8.99 - - [04/Dec/2022:16:21:23 +0800] "GET /name HTTP/1.1" 301 169 "-" "http://192.168.8.111/name" "HTTP/1.1""PostmanRuntime/7.29.2" "-" "192.168.8.198:19999"
2022/12/04 16:21:23 [error] 89456#0: *68 "/nginx/html/name/index.html" is not found (2: No such file or directory), client: 192.168.8.99, server: , request: "GET /name/ HTTP/1.1", host: "192.168.8.111:20000", referrer: "http://192.168.8.111:20000/name"
192.168.8.99 - - [04/Dec/2022:16:21:23 +0800] "GET /name/ HTTP/1.1" 404 153 "http://192.168.8.111:20000/name" "http://192.168.8.111/name/" "HTTP/1.1""PostmanRuntime/7.29.2" "-" "-"
一、proxy_pass 官网给出的四种场景验证说明
语法: proxy_pass URL;
默认: —
背景: location,if in location,limit_except
1. proxy_pass 带有URI
官网原文: If the proxy_pass
directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:
翻译:如果 proxy_pass 的位置指定URI,那么当请求到NGINX服务器时,与location匹配的请求URI部分,将会被proxy_pass位置指定的URI取代。
- 说人话:proxy_pass 指令中指定了uri ,此时location 处的匹配只做请求验证不会替换proxy_pass处的uri
#第一种:
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}
#当发起请求为:http://www.nginx.com/name/,proxy_pass 不会自动把/name/替换为/remote/,最后的请求的格式依然为:http://127.0.0.1/remote/
#第二种
location /name/ {
proxy_pass http://127.0.0.1/; #注意此处的/ ,这也是uri的一部分
}
# 注意和第一种相比这里的URI只有"/",最后的请求格式仍然是:http://127.0.0.1/
2. proxy_pass 不带URI
官网原文:If proxy_pass
is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
翻译:如果在没有URI的情况下指定proxy_pass
,则请求URI将以处理原始请求时客户端发送的相同形式传递给服务器,或者在处理更改的URI时传递完整的规范化请求URI:
- 说人话:proxy_pass 指令中没有指定uri ,发起请求并和location处的匹配验证成功后,将匹配的内容传递给proxy_pass
- 在1.1.12版本之前,如果在没有URI的情况下指定
proxy_pass
,在某些情况下,可能会传递原始请求URI,而不是更改的URI。
location /some/path/ {
proxy_pass http://127.0.0.1;
}
#通过此配置进行解释:
发起请求为:http://www.nginx.com/some/path/,会将请求的URI部分(some/path/),传递给proxy_pass,最后像后端服务器请求的格式为:http://127.0.0.1/some/path/
3. proxy_pass 使用rewrite
官网原文: When the URI is changed inside a proxied location using the rewrite directive, and this same configuration will be used to process a request (break
):
翻译:当URI在使用[重写]指令的代理位置内被改变,而这个相同的配置将被用来处理一个请求
说人话:使用rewrtie 时,会将重写后的uri 传递给proxy_pass 指令
这里要注意两个细节:
(1) rewrite 的flag位必须是break
(2) proxy_pass后面不能有uri信息。
location /name/ {
rewrite /name/([^/]+) /users?name=$1 break;
proxy_pass http://127.0.0.1;
}
4. 当在proxy_pass中使用变量
官网原文:When variables are used in proxy_pass
:
In this case, if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.
翻译:在使用变量时
在这种情况下,如果URI被指定在指令中,它将被原封不动地传递给服务器,取代原来的请求URI。
location /name/ {
proxy_pass http://127.0.0.1$request_uri;
}
二 、基于以上说明对其他用法测试验证的结论
$request_uri full original request URI (with arguments),请求时的uri 地址会被完全的继承下来。
1. 在proxy_pass 中使用变量时前面或者后面可以有其他路径
发起请求:http://127.0.0.1:20000/path/name/local/
server{
listen 20000;
access_log /nginx/logs/test.log main;
error_log /nginx/logs/test.log;
location ~ /path {
proxy_pass http:///127.0.0.1:19999/aaa$request_uri;
}
}
2. 在proxy_pass 中配合upstream模块和变量时前面或者后面可以有其他路径
发起请求:http://127.0.0.1:20000/path/name/local/
upstream pro{
server 127.0.0.1:19999;
}
server{
listen 20000;
access_log /nginx/logs/test.log main;
error_log /nginx/logs/test.log;
location ~ /path/name/local {
proxy_pass http://pro/aaa$request_uri;
}
}
三、localtion 正则匹配报错
nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in ...
遇到如上错误,说明location的正则匹配和proxy_pass 处指定的URI重名,可以使用变量代替这个重名问题
#错误配置:
server{
listen 20000;
access_log /nginx/logs/test.log main;
error_log /nginx/logs/test.log;
location ~ /test/server/query {
proxy_pass https://192.168.8.143:19000/test/server/query;
}
}
#正确配置:
server{
listen 20000;
access_log /nginx/logs/test.log main;
error_log /nginx/logs/test.log;
location ~ /test/server/query {
proxy_pass https://192.168.8.143:19000$request_uri;
}
}