前言
声明 1
前端做反向代理时一般会在接口前增加一个 api
路径,如 /api/user
,但后端并没有这么个东西,那么就会导致一些问题。
声明 2
location
一般采用前缀匹配的模式。
日常使用中虽可采用 rewrite
解决多余路径的问题(此处可如此使用的缘由是 rewrite
的处理阶段在 proxy_pass
之前)。
location /api {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
# 路径重写
rewrite /api/(.*) /$1 break;
proxy_pass http://localhost:8123;
}
location /msa-file/ {
proxy_pass http://172.17.0.1:8075/MSA.File/;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
但探索一下 location
+ proxy_pass
也是不错的选择。
规则
Syntax: proxy_pass URL;
Default: —
Context: location, if in location, limit_except
其中唯一需要注意的是,当 proxy_pass
后无 /
时为相对地址,有则为绝对地址。
1. 相对地址
相对地址时会将 location
匹配的 uri
加入代理。
server {
listen 8085;
server_name localhost;
location / {
return 200 "8084 \n";
}
}
server {
listen 8083;
server_name localhost;
location /api {
proxy_pass http://localhost:8085;
}
}
server {
listen 8084;
server_name localhost;
location /api {
proxy_pass http://localhost:8085/app;
}
}
curl | 8083 | 8084 |
---|---|---|
localhost:8083/api | /api | /api |
localhost:8083/api/user | /api/user | /api/user |
localhost:8084/api | /api | /app |
localhost:8084/api/user | /api/user | /app/user |
localhost:8084/apipp/user | /apipp/user | /apppp/user |
2. 绝对地址
绝对地址则不会将 location
匹配的 uri
加入代理,即直接丢弃。
server {
listen 8085;
server_name localhost;
location / {
return 200 "8084 \n";
}
}
server {
listen 8083;
server_name localhost;
location /api {
proxy_pass http://localhost:8085/;
}
}
server {
listen 8084;
server_name localhost;
location /api {
proxy_pass http://localhost:8085/app/;
}
}
# 解决多余的 `/`
server {
listen 8086;
server_name localhost;
location /api/ {
proxy_pass http://localhost:8085/app/;
}
}
curl | proxy | target |
---|---|---|
localhost:8083/api | /api | / |
localhost:8083/api/user | /api/user | //user |
localhost:8084/api | /api | /app/ |
localhost:8084/api/user | /api/user | /app//user |
localhost:8084/apipp/user | /apipp/user | /app/pp/user |
localhost:8086/api | /api | location 未匹配,所以不进入 proxy |
localhost:8086/api/user | /api/user | /app/user |
可以观测到少了匹配到的 api
部分,而作为路径的 /
未匹配到显得多余起来,解决的方案是使 location
匹配到 /
即可。
proxy_redirect
proxy_redirect是Nginx的一个指令,它用于替换反向代理所返回的响应头中的Location和Refresh字段来将页面重定向指向正确的地址。
proxy_redirect的使用方法 在Nginx的配置文件中,我们可以使用以下语法来启用proxy_redirect:
proxy_redirect redirect_regex substitute_string;
假设我们有一个网站https://example.com
,它的反向代理位于https://proxy.example.com
,我们使用以下配置将请求发送到反向代理:
location / {
proxy_pass https://proxy.example.com;
proxy_redirect https://proxy.example.com/ /;
...
}
现在,当用户访问https://example.com/foo/bar
时,Nginx会将该请求发送到https://proxy.example.com/foo/bar
。
- 在这个例子中,proxy_redirect的参数
redirect_regex
为https://proxy.example.com/
,substitute_string为/。因此,任何返回的响应头中包含https://proxy.example.com/
的字符串将被替换为 /。
这意味着,如果代理服务器返回https://proxy.example.com/abc
,Nginx会将其替换为/abc。
假设我们有一个网站https://example.com
,它的反向代理位于https://proxy.example.com
,我们使用以下配置将请求发送到反向代理:
location / {
proxy_pass https://proxy.example.com;
proxy_redirect default;
...
}
现在,当用户访问https://example.com/foo/bar
时,Nginx会将该请求发送到https://proxy.example.com/foo/bar
。
- 在这个例子中,proxy_redirect的参数
redirect_regex
为default,substitute_string
为$scheme://$host/
。 - 这意味着,Nginx会将任何返回的响应头中包含https://proxy.example.com的部分替换为请求的协议和主机名,也就是
https://example.com
。
查看常用配置参数
# 用户请求的时候HOST的值是game.test.com, 那么代理服务会像后端传递请求的还是game.test.com
proxy_set_header Host $http_host;
# 将$remote_addr的值放进变量X-Real-IP中,$remote_addr的值为客户端的ip
proxy_set_header X-Real-IP $remote_addr;
# 客户端通过代理服务访问后端服务, 后端服务通过该变量会记录真实客户端地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# nginx代理与后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 10s;
# nginx代理等待后端服务器的响应时间
proxy_read_timeout 10s;
# 后端服务器数据回传给nginx代理超时时间
proxy_send_timeout 10s;
# nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传, 不是全部接收完再传给客户
proxy_buffering on;
# 设置nginx代理保存用户头信息的缓冲区大小
proxy_buffer_size 8k;
# proxy_buffers 缓冲区
proxy_buffers 8 8k;
# 状态标记
proxy_next_upstream http_404 http_500 http_502 http_503 http_504 http_403 http_429;
nginx中host、http_host和$proxy_host区别
变量 | 是否显示端口 | 值 |
---|---|---|
$host | 不显示端口 | 浏览器请求的ip,不显示端口 |
$http_host | 端口存在则显示 | 浏览器请求的ip和端口号 |
$proxy_host | 默认80端口不显示,其它显示 | 被代理服务的ip和端口号 |
- 配置反向代理时,接口请求报404问题 应用描述:前端应用域名为A(ww.a.com), 后端服务域名为B(www.b.com); 为了解决跨域问题,配置nginx反向代理如下:
proxy_set_header Host $host;
location ^~ /api/ {
rewrite "^/api/(.*)$" /$1 break;
proxy_pass http://www.b.com;
}
方案一:将proxy_set_header注释掉 方案二:修改反向代理配置,设置请求头Host,如下所示:
location ^~ /api/ {
rewrite "^/api/(.*)$" /$1 break;
proxy_pass http://www.b.com;
proxy_set_header Host $proxy_host; //方式一:设置请求头host为www.b.com的ip和端口号
proxy_set_header Host www.b.com; //方式二:设置请求host为www.b.com
}