作为一款Web服务器软件,Nginx实现了Web服务器的基本功能,用户通过简单的配置指令就可以快速完成Web服务器的搭建。它还是网络通信协议处理软件,支持TCP/UDP、HTTP、HTTP/2、gRPC、FastCGI、SCGI、uWSGI、WebDAV等协议的处理,并实现了相应通信协议的请求解析、长连接、代理转发、负载均衡、会话保持等互联网架构中常见的应用功能。同时,它还是一款高并发服务软件,其采用的固定数量的多进程模型、事件驱动处理机制、工作流处理方式及模块化架构等软件开发设计,已成为高并发服务软件开发的典范。
重定向,通常是指URL重定向,也称为URL转发。是指在原链接的地址变更且不想影响搜索排名或执行任务异步显示等场景时,将原链接的访问的新地址发送给客户端并重新发起请求的访问方式。Nginx在作为代理服务器应用中,经常会遇到被代理服务器返回URL重定向的场景。本文主要介绍Nginx重定向方式。
01重定向方式
客户端重定向比较常用的有如下有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响应头字段属性信息。配置格式如下所示:
页面重定向的属性字段为“Refresh”。当显示页面时,浏览器会检测该属性并重定向到指定的url地址,配置方式如下:
客户端浏览器2秒后自动重定向到指定的URL: http://www.nginxbar.com
执行优先级
上述两种方式的执行优先级会因浏览器客户端的不同有一定差异,大多数浏览器客户端会遵循HTTP协议的重定向机制最先触发,HTML的元信息标签会在HTTP协议的重定向机制未设置的情况下触发。
02Nginx的重定向处理
Nginx 提供了多个配置指令可以灵活的处理被代理服务器中的URL重定向响应,通常被分为两种方法,一种是Nginx将被代理服务器的URL重定向返回给客户端,由客户端进行处理,见实例一、二。第二种方式是Nginx处理URL重定向后将最终的结果返回给客户端,见实例三。
实例一:状态码转发
在向统一网关迁移时,由于被代理的服务器多数会配有原有域名,为保持原有用户访问方式不变,所以可使用Nginx将后端服务的URL重定向进行url替换,实现平滑迁移。
配置样例
location /api/ { proxy_pass http://backend; # 修改被代理服务器种响应头“Location”字段的内容为新的域名 proxy_redirect ~^/(.*) http://$http_host/api/$1;}
实例二: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 '' '';}
实例三:获取重定向的真实内容
对于某些应用场景中,为提高访问效率,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; }}
Nginx 提供了内置变量 “$upstream_http_<响应头字段名>” 可获取响应头字段属性值
@error_page 是内部循环,最大循环次数为10次。