当Nginx遇到302原创
# 当Nginx遇到重定向
重定向,通常是指URL重定向,也称为URL转发。是指在原链接的地址变更且不想影响搜索排名或执行任务异步显示等场景时,将原链接的访问的新地址发送给客户端并重新发起请求的访问方式。Nginx在作为代理服务器应用中,经常会遇到被代理服务器返回URL重定向的场景。
# 重定向方式
客户端重定向比较常用的有如下有2种实现方式,分别是HTTP协议的响应状态码和HTML的元信息标签。
# 基于HTTP协议的重定向
HTTP协议中,由服务器端发送特殊的响应状态码来触发浏览器客户端实现重定向,HTTP协议的响应状态码为3xx,常用的有如下几个状态码:
状态码 | 应用场景 | 处理方法 | 说明 |
---|---|---|---|
301 | 永久重定向 | GET、HEAD | 重定向的HTTP方法为GET |
308 | 永久重定向 | ALL | 重定向的HTTP方法取决于第一次访问的HTTP方法 |
302 | 临时重定向 | GET、HEAD | 重定向的HTTP方法为GET |
303 | 临时重定向 | GET、HEAD | 重定向的HTTP方法为GET |
307 | 临时重定向 | ALL | 重定向的HTTP方法取决于第一次访问的HTTP方法 |
- 重定向的URL地址由响应头字段“Location”的属性定义
# 基于HTML的元信息标签的重定向
在一些场景中,由于开发人员没有Web服务器的配置权限,所以会利用Html元信息标签提供的“http-equiv”属性来实现重定向,该属性可以定义响应头的信息,如响应体内容编码、当前内容浏览器缓存方式、页面跳转、网站内容描述等常见HTTP响应头字段属性信息。配置格式如下所示:
<meta http-equiv="属性字段" content="属性字段值">
页面重定向的属性字段为“Refresh”。当显示页面时,浏览器会检测该属性并重定向到指定的url地址,配置方式如下:
<meta http-equiv="Refresh" content="2"; URL="http://www.nginxbar.com/">
2
- 客户端浏览器2秒后自动重定向到指定的URL: http://www.nginxbar.com
# 执行优先级
上述两种方式的执行优先级会因浏览器客户端的不同有一定差异,大多数浏览器客户端会遵循HTTP协议的重定向机制最先触发,HTML的元信息标签会在HTTP协议的重定向机制未设置的情况下触发。
# Nginx的重定向处理
Nginx 提供了多个配置指令可以灵活的处理被代理服务器中的URL重定向响应,通常被分为两种方法,一种是Nginx将被代理服务器的URL重定向返回给客户端,由客户端进行处理,见实例一、二。第二种方式是Nginx处理URL重定向后将最终的结果返回给客户端,见实例三。
# 实例一:状态码URL转发
在向统一网关迁移时,由于被代理的服务器多数会配有原有域名,为保持原有用户访问方式不变,所以可使用Nginx将后端服务的URL重定向进行url替换,实现平滑迁移。
配置样例
location /api/ {
proxy_pass http://backend;
# 修改被代理服务器种响应头“Location”字段的内容为新的域名
proxy_redirect ~^/(.*) http://$http_host/api/$1;
}
2
3
4
5
# 实例二:HTML元信息标签的修改
对部分使用HTML元信息标签定义URL重定向的网站,可以使用Nginx配置指令将原有的域名替换为新的域名。
配置样例
location /books {
# 设置请求头,像后端请求无压缩的响应数据
proxy_set_header Accept-Encoding '';
proxy_pass http://www.nginxbar.com;
# 进替换一次
sub_filter_once on;
# 将http://www.nginxbar.com/ 替换 为http://www.nginxbar.org/books
sub_filter '<meta http-equiv="Refresh" content="2"; URL="http://www.nginxbar.com/">' '<meta http-equiv="Refresh" content="2";URL="http://www.nginxbar.org/books">';
}
2
3
4
5
6
7
8
9
10
11
# 实例三:获取重定向的真实内容
对于某些应用场景中,为提高访问效率,Nginx会直接将302的重定向在服务端处理,并将最终的结果返回给客户端。
配置样例
server {
listen 8099;
resolver 114.114.114.114 valid=30s;
# Nginx处理状态码大于300的响应结果
proxy_intercept_errors on;
# 启用多级错误跳转
recursive_error_pages on;
location ~ /proxy {
proxy_pass http://backend;
error_page 301 302 307 308 = @error_page_302;
}
location @error_page_302 {
set $new_redirect_location '$upstream_http_location';
proxy_pass $new_redirect_location;
# 支持多层3XX跳转
error_page 301 302 307 = @error_page_302;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- Nginx 提供了内置变量 “$upstream_http_<响应头字段名>” 可获取响应头字段属性值
- @error_page 是内部循环,最大循环次数为10次