建设品牌网站,电脑上必玩的游戏,免费婚纱网站模板,seo营销学校参考;
404 - 墨天轮
深度硬核文:Nginx的301重定向处理过程分析 - 知乎
Nginx的301状态码处理逻辑设计
HTTP协议中3xx开头的状态响应码都是表示重定向的响应。根据RFC的定义#xff1a;
301 Moved Permanently
302 Found
303 See Other
307 Temporary Redirect
301是永…参考;
404 - 墨天轮
深度硬核文:Nginx的301重定向处理过程分析 - 知乎
Nginx的301状态码处理逻辑设计
HTTP协议中3xx开头的状态响应码都是表示重定向的响应。根据RFC的定义
301 Moved Permanently
302 Found
303 See Other
307 Temporary Redirect
301是永久重定向。如果使用Nginx作为HTTP 服务器那么当用户输入一个不存在的地址之后基本上会有两种情况返回404状态码或者301状态码。404 Not Found不做讨论只是说下301 Moved Permanently的处理过程。
页面重定向功能会在什么样的情况下被触发
答案是Nginx负责设置301 Moved Permanently状态码。但nginx.conf控制Nginx如何处理301 Moved Permanently状态码换句话说要不要进行页面重定向和怎么重定向完全是用户配置的结果六种分支的选择完全是根据用户的配置来决定的。
根据源代码Nginx的算法逻辑设计是分成两个部分的。第一部分是设置状态码第二部分是对应状态码的实际响应处理。
Nginx和浏览器之间的通讯过程比如一次正常的HTTP 访问过程如下图。 从逻辑顺序上来说Nginx会先设置好状态码然后根据状态码来构造Response Header和Body最后发送给浏览器让浏览器渲染页面内容。
301 Moved Permanently状态码和200 OK状态码的处理过程是一致的。Nginx主动设置301 Moved Permanently状态码只有一种情况当用户输入了一个url地址最后的部分是一个文件目录。比如 http://www.test.com/index, Nginx在运行过程中没有找到index这个文件但发现了index是个目录。于是本次访问的状态码就会被设置成301 Moved Permanently。 但注意设置成301 Moved Permanently不一定会导致浏览器重定向。从HTTP定义来说导致浏览器触发重定向操作是因为浏览器收到了一个Locationresponse header
让我们来看看Location的定义说明很明确的说明了Location的作用。
The Location response header indicates the URL to redirect a page to. It only provides a meaning when served with a3xx (redirection) or 201(created) status response.
Nginx在Response Header里写入一个Location之后。浏览器可以根据Location来控制重定向过程。逻辑过程如上图。而且nginx.conf文件中的配置将影响到Location URL的生成方式。
nginx.conf中配置项的作用
nginx.conf文件在哪个环节起作用呢答案就是设置Location之前。 一般情况下我们会在nginx.conf中配置absolute_redirect server_name_in_redirect和port_in_redirect以便到达个性化的重定向功能。这三个配置项的作用是很多人明白的但对于逻辑顺序很少有文章提到。
重定向三配置
absolute_redirect server_name_in_redirect和port_in_redirect三个设置项中根据Nginx的源代码中Response Header处理算法逻辑Nginx能够控制重定向的关键配置项是:absolute_redirect在整个Nginx代码中absolute_redirect在控制在Response Header如何增加Location url。
absolute_redirect设置成On则生成absolute url作为Location url。absolute_redirect设置成Off则生成relative url作为 Location url。
absolute url是包含完整信息的url比如http://www.test.com:8080/index/1.html 这样的URL地址relative url 则省略了服务器名字和端口号比如 /index/1.html
因为relative url没有端口号没有Host名字所以absolute_redirect 设置On的时候server_name_in_redirect和port_in_redirect两项设置才会起作用。
我花了点时间仔细阅读了Nginx的相关源代码并画了流程图。 从以上逻辑过程 absolute_redirectserver_name_in_redirectport_in_redirect 三项配置共同控制了生成字符串 “Location: http://server_name:port/test/”的结果。
server_name_in_redirect 控制URL中的Server Name也就是Host使用哪个值port_in_redirect控制URL中的port是使用哪个值。通过这三个配置项最终决定了Nginx返回给浏览器的Location内容。
用MindMap来表达就是 备注header_in.server是nginx源代码中的变量指向用户输入的url的服务器名字部分。根据以上脑图我们可以很清楚的看到最终我们只有六个分支结果。
案例分析
依据上面的分析我们具体举个非常疑难的例子看看如何解决问题。
1,问题http://www.test.com:888/index被错误的重定向至http://www.test.com/index/这种情况多见于使用NAT做端口映射或者是用容器来运行Nginx。内部服务器或者容器中nginx监听的是80端口号
而我们的期望答案是http://www.test.com:888/index重定向至http://www.test.com:888/index/
2,分析和解答假设Nginx使用默认设置
absolute_redirect:on
server_name_in_redirect:off
port_in_redirect :on
这个问题看似丢失了端口号实际上是暴露了nginx的内部端口号。这种情况下port_in_redirect不管设置成on或者off都不会起作用。
port_in_redirect onnginx监听80端口默认80端口号不需要在url中设置【3号分支】结果是http://www.test.com/index/
port_in_redirect offnginx不设置port数据【5号分支】结果还是http://www.test.com/index/
我们会发现在这里无论怎么调整server_name_in_redirect【12号分支】和port_in_redirect的onoff都是无效的。因为1号至5号分支都没有包含这种情况。解决问题的方向错了解决方案当然就是错误的。
实际的解决方案有两个 rewrite【分支以外】 absolute_redirect:off【六号分支】 rewrite是通过脚本来控制nginx的运行过程不在上面的配置分支中。具体操作可以参考下面的设置
rewrite [^/]$ $scheme://$http_host$uri/ permanent;备注rewrite的操作方式依据不同的目录结构可能略有不同请根据实际情况来设置。
absolute_redirect:off就是六号分支absolute_redirect:off之后Nginx返回Location:/index/,但这个方式也许会带来其他问题。
absolute_redirect
1. 设置absolute_redirect
1 absolute_redirect为off。
server { server_name sample_test.xyz sample_preview.xyz; server_name_in_redirect off; listen 9098; port_in_redirect on; absolute_redirect off; root html/; }
当前absolute_redirect指令设置的是off此时头部的Location部分是不会出现协议、主机名还有端口。 2absolute_redirect为on。
server { server_name sample_test.xyz sample_preview.xyz; server_name_in_redirect off; listen 9098; port_in_redirect on; absolute_redirect on; root html/; }
当absolute_redirect指令设置为on头部的Location部分则出现协议、主机名还有还有端口。 2. 设置server_name_in_redirect
1 server_name_in_redirect 为off。
server { server_name sample_test.xyz sample_preview.xyz; server_name_in_redirect off; listen 9098; port_in_redirect on; absolute_redirect on; root html/; }
将server_name_in_redirect指令设置为off会使用请求头中Host的值。这里杨杨在请求时添加头部信息可以看到Location中的域名变成了aaa。 2server_name_in_redirect 为on。
server { server_name sample_test.xyz sample_preview.xyz; server_name_in_redirect on; listen 9098; port_in_redirect on;absolute_redirect on; root html/;}
将server_name_in_redirect指令设置为on会location会使用配置文件中的server_name3. 设置port_in_redirect 1 port_in_redirect为off。
server { server_name sample_test.xyz sample_preview.xyz; server_name_in_redirect off; listen 9098; port_in_redirect off; absolute_redirect on; root html/; }
当port_in_redirect指令的值设置为offlocation中就不会展示出访问的端口号。 在前几个例子中port_in_redirect指令的值为on此时location中会展示出端口号。