Nginx 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_redirect,server_name_in_redirect,port_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 = on,nginx监听80端口,默认80端口号不需要在url中设置【3号分支】,结果是http://www.test.com/index/

port_in_redirect = off,nginx不设置port数据【5号分支】,结果还是http://www.test.com/index/

我们会发现,在这里无论怎么调整server_name_in_redirect【1,2号分支】和port_in_redirect的on,off都是无效的。因为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部分是不会出现协议、主机名还有端口。


2)absolute_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。



2)server_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_name


3. 设置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指令的值设置为off,location中就不会展示出访问的端口号。



在前几个例子中,port_in_redirect指令的值为on,此时location中会展示出端口号。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/5907.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

seq2seq、attention、self-attention、transformer、bert

seq2seq seq2seq:输入序列,输出序列,将输入的语言转为一个向量,最后输出再将向量转为语言shortcoming:The final state is incapable of remembering a long sequence.即太长了记不住 attention 用attention可以改进seq2seq中的…

Day 63 : 集成学习之 AdaBoosting (1. 带权数据集)

63.1 AdaBoosting基本算法:先从初始训练集训练一个弱学习器,在根据弱学习器的表现对训练样本进行权重调整,经过若干轮之后,将得到一组分类器,将数据输入这组分类器后会得到一个综合且准确的的分类结果。“三个臭皮匠&a…

C++ 单例模式(介绍+实现)

文章目录 一. 设计模式二. 单例模式三. 饿汉模式四. 懒汉模式结束语 一. 设计模式 单例模式是一种设计模式 设计模式(Design Pattern)是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结。 为什么要有设计模式 就像人类历史发展会…

WEB:wife_wife

背景知识 JavaScript原型链污染 题目 先尝试一下,注册了管理员账号 这里不知道邀请码,所以没有勾选 答案不正确 这里借鉴其他大佬的思路 查看源代码才知道,后端没有数据库,所以sql注入是不可能的 // post请求的路径 app.pos…

【网络】应用层——协议定制 | 序列化和反序列化 | 初识http

🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言:你只管努力,剩下的交给时间! 在前面本喵已经带大家见识过了scoket网络通信的样子,现在开始深入学习网络的原理&#xff…

机器学习 day29(高偏差、高方差,参数d对模型的影响)

1. 高偏差、高方差、拟合能力、泛化能力 偏差和方差分别代表拟合能力和泛化能力若给左图数据集拟合一阶多项式(d取1),则该模型有很高的偏差(欠拟合)。因为它对训练集和验证集的表现均不好,所以Jtrain很高…

快手内推(2024校招,社招)

校招 校招可以直接投递,如果想投递指定部门或岗位的可以私聊我。可以帮看简历和面试状态,加快推进。 内推码:vlxMTFNBS 专属内推链接:https://campus.kuaishou.cn/#/campus/jobs?codevlxMTFNBS 社招 社招内推私聊,可…

[Java]详解什么是注解以及如何自定义注解?

文章目录 一、什么是注解(1).注解的作用(2).注解的格式(3).注解在哪里使用 二、注解的类型(1).内置注解(2).元注解(3).自定义注解 三、自定义注解实现及测试结果: 一、什么是注解 (1).注解的作用 ①:注解一般用于对程序的说明,就像注释一样…

RabbitMQ的交换机的四种类型

RabbitMQ的交换机的四种类型 一、Direct类型交换机 Direct类型交换机 ///1.在发送消息的时候,通过Direct类型的路由转发; //要求Direct类型交换机和队列绑定;绑定需要一个标识,生产者在发送消息的时候,也需要指定一个…

windows系统修改mysql8配置文件,关闭ssl验证

如何寻找配置文件 我的电脑,右键,管理,服务 找到MySQL8 右键,属性 找到配置文件位置 通常情况下的默认路径是: C:\ProgramData\MySQL\MySQL Server 8.0\my.ini 如何关闭SSL验证 打开 my.ini 配置内容如下&#x…

算法:HJ23 删除字符串中出现次数最少的字符

描述 实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。 数据范围:输入的字符串长度满足 1≤n≤20 ,保…

【100天精通python】Day7:数据结构_列表 List的创建、删除、访问、遍历、统计、排序、推导等使用

目录 1 列表的创建 2 列表的删除 3 访问列表元素 4 遍历列表 5 添加修改删除列表元素 6 对列表进行统计和计算 7 对列表进行排序 8 列表推导式 9 多维列表 在Python中,列表是一种有序的可变数据类型,用于存储一组元素。 列表使用方括号“[] ”来…

Qt5.14.2下载及安装

1. 下载 https://download.qt.io/archive/qt/5.14/5.14.2/ 由于Qt 自从5.15版本开始,对非商业版本(也就是开源版本),不提供已经制作好的离线exe安装包。所以,对于5.15(含)之后的版本&#xff…

软件智能:aaas系统全部内容 之序 零-AI三部曲 (重新汇总整理)

想法ideal 这次的重新整理是希望作为所有过去整理过和思考过的内容的一个类似词典编纂的工作,将之前的东西打乱以后能挂靠在这个词典的下面。 想法是以“人工智能”的语义为焦点(统一行为特征,注1),并将语用作为结构…

Idea 设置类和方法的注释(获取参数)

Idea 添加注释:类注释、方法注释 类注释 方法注释 类注释 File–Setting–Editor–File and Code Templates–Class: 注释模板: /** **description: *author: fqtang*time: ${DATE} ${TIME}* */ 操作截图: 效果: 方法注释 为了…

图数据库Neo4j学习二——cypher基本语法

1命名规范 名称应以字母字符开头,不以数字开头,名称不应包含符号,下划线除外可以很长,最多65535( 2^16 - 1) 或65534字符,具体取决于 Neo4j 的版本名称区分大小写。:PERSON和:Person是:person三个不同的标签&#xff…

Langchain 使用 OpenAI 聊天模型

Langchain 使用 OpenAI 聊天模型 本笔记本介绍了如何开始使用 OpenAI 聊天模型。 示例代码, from langchain.chat_models import ChatOpenAI from langchain.prompts.chat import (ChatPromptTemplate,SystemMessagePromptTemplate,AIMessagePromptTemplate,Human…

Jmeter+Jenkins+Ant自动化持续集成环境搭建

一、安装准备 1.JDK:jdk-8u121-windows-x64 2.jmeter工具:apache-jmeter-2.13 3.ANT工具:apache-ant-1.9.7-bin 4.jenkins工具:jenkins-2.32.2 二、软件安装 1.JDK的安装 >双击JDK安装包,选择安装路径(本人是…

详细总结Webpack5的配置和使用

打包工具 使用框架(React、Vue),ES6 模块化语法,Less/Sass 等 CSS预处理器等语法进行开发的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、CSS 等语法,才能运行。 所以需要打包工具帮我们做完这些事。除此之…

3、C# 方法构成

上一节,我们讲述了程序的基本构成。由大到小分别为”解决方案-->项目-->类-->方法“。 这一节,我们讲讲方法。 方法可以说是程序的基本构成单位。假如把方法抽象成点的话,我们可以认为程序是一个树状的结构。树根,就是我们的起点方法,也叫主方法。这一点,基本…