前言

声明 1

前端做反向代理时一般会在接口前增加一个 api 路径,如 /api/user,但后端并没有这么个东西,那么就会导致一些问题。

声明 2

location 一般采用前缀匹配的模式。

alt

日常使用中虽可采用 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;
  }
}
curl80838084
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/;
  }
}
curlproxytarget
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/apilocation 未匹配,所以不进入 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_regexhttps://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
}