[nginx] nginx源码分析--proxy模式下nginx的自动重定向auto_redirect
描述
我们配置了一个proxy模式下的nginx,
upstream backend-test {
server 127.0.0.1:;
}
server {
listen ;
location = /nginx/hwwc/ {
proxy_pass http://backend-test;
proxy_redirect off;
}
location / {
return ;
}
}
访问 http://t103:8080/nginx/hwwc/ 可以正常访问80端口的服务. 访问curl http://t103:8080/nginx/hwwc 的时候, 会返回301重定向. 他们的区别是结尾是否有一个"/"
┬─[tong@T7:~/Src/thirdparty/nginx.git]─[:: PM]
╰─>$ curl http://t103:8080/nginx/hwwc
<html>
<head><title> Moved Permanently</title></head>
<body bgcolor="white">
<center><h1> Moved Permanently</h1></center>
<hr><center>nginx/1.12.</center>
</body>
</html>
结论: 这个问题的原因是, 访问hwwc时触发了nginx的auto_rediect功能. 将请求重定向到了hwwc/
分析过程如下:
调试日志
首先打开nginx的调试. 使用--with-debug选项编译的nginx可以打开此功能, 如下配置:
参考:https://nginx.org/en/docs/ngx_core_module.html#debug_connection
events {
debug_connection 192.168.7.1;
}
在error.log里能看见如下日志: (摘录关键内容)
... ...
2019/09/02 18:37:49 [debug] 23137#0: *70 test location: "/"
2019/09/02 18:37:49 [debug] 23137#0: *70 test location: "nginx/hwwc/"
2019/09/02 18:37:49 [debug] 23137#0: *70 using configuration "=/nginx/hwwc/"
// :: [debug] #: * http cl:- max:
// :: [debug] #: * http finalize request: , "/nginx/hwwc?" a:, c:
// :: [debug] #: * http special response: , "/nginx/hwwc?"
// :: [debug] #: * http set discard body
// :: [debug] #: * xslt filter header
// :: [debug] #: * posix_memalign: 000055830C085F80: @
// :: [debug] #: * HTTP/1.1 Moved Permanently
Server: nginx/1.12.
Date: Mon, Sep :: GMT
Content-Type: text/html
Content-Length:
Location: http://t103:8080/nginx/hwwc/
Connection: keep-alive
通过上边的日志我们能见到, nginx在location"/" 与 "nginx/hwwc/" 中进行选择, 最后选择了"nginx/hwwc/", 然后触发了301.
代码分析
一
根据上边的日志, 我们通过主要的的关键字"test location" 和 "using configuration" 定位到如下代码:
nginx/src/http/ngx_http_core_module.c::ngx_http_core_find_static_location():1443
if (len + == (size_t) node->len && node->auto_redirect) {
r->loc_conf = (node->exact) ? node->exact->loc_conf:
node->inclusive->loc_conf;
rv = NGX_DONE;
}
在location选择的时候, 如果URI字符串比location字符串多了一个字符(也就是"/"),并且前边的字符都相等, 同时node结构体的变量auto_redirect也是true的. 就认为命中了当前location.
也就是说URI"hwwc"会在精确匹配location的检查中匹配到location"hwwc/"
二
nginx/src/http/ngx_http.c::ngx_http_create_locations_tree():1093
node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
|| (lq->inclusive && lq->inclusive->auto_redirect));
nginx的全局代码中有两个auto_redirect, 一个是(一)中的node结构体. 另一个是config中的结构体.
node中的结构体会通过config中的设置进行赋值. 如该段代码所述.
三
nginx/src/http/modules/ngx_http_proxy_module.c::ngx_http_proxy_pass():3594
if (clcf->name.len && clcf->name.data[clcf->name.len - ] == '/') {
clcf->auto_redirect = ;
}
config中的auto_redirect, 当检测到location以"/"结尾的时候, 会自动赋值auto_redirect 为true, 并通过(二)传递到运行时.
这段赋值代码, 除了在proxy模块中, 同时还存在与fastcgi, grpc, memcached, scgi, uwsgi模块中.
四
nginx/src/http/ngx_http_core_module.h
struct ngx_http_core_loc_conf_s {
... ...
unsigned auto_redirect:;
ngx_flag_t absolute_redirect; /* absolute_redirect */
ngx_flag_t server_name_in_redirect; /* server_name_in_redirect */
ngx_flag_t port_in_redirect; /* port_in_redirect */
... ...
}
nginx/src/http/ngx_http_core_module.c
static ngx_command_t ngx_http_core_commands[] = {
{ ngx_string("absolute_redirect"),
... ...
{ ngx_string("server_name_in_redirect"),
... ...
{ ngx_string("port_in_redirect"),
... ...
}
分析配置流程中的代码. location中与redirect相关的配置大概一共有四个, 其中auto_redirect是不可配置的. 其他三个可以通过配置文件设置. 但是均与auto_redirect没有逻辑耦合关系.
综上. auto_redirect是不可通过配置修改的. 由URI的结尾是否有"/"自动设置.
如果要改变这一行为,需要进行代码基本的修改。
通过官方文档印证
查看, ngnix的官方文档, 针对该问题有如下的描述,和解决建议. 与我们通过源码进行的分析保持一直:
https://nginx.org/en/docs/http/ngx_http_core_module.html#location
如果, 要屏蔽这个重定向问题, 应该明确的对不带"/"的location进行指定.
另外,
除了以上提到的几个配置, 还有一个proxy_redirect的配置.
https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect
通过简单测试,发现当前场景下,该配置并不生效. 应该是由于我们这个场景下个redirect使用proxy发的. 而这个配置项
是针对backend发来的redirect消息进行修改的.
以后可以读一下代码进行确认. 目前先通过测试做这样的黑盒判断.
其他
serverfault上也有人提出同样的问题. 结论与我们的分析一致.
[nginx] nginx源码分析--proxy模式下nginx的自动重定向auto_redirect的更多相关文章
- 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 百篇博客分析OpenHarmony源码 | v36.04
百篇博客系列篇.本篇为: v36.xx 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CP ...
- QTimer源码分析(以Windows下实现为例)
QTimer源码分析(以Windows下实现为例) 分类: Qt2011-04-13 21:32 5026人阅读 评论(0) 收藏 举报 windowstimerqtoptimizationcallb ...
- SpringAOP使用及源码分析(SpringBoot下)
一.SpringAOP应用 先搭建一个SpringBoot项目 <?xml version="1.0" encoding="UTF-8"?> < ...
- JDK源码分析(三)——HashMap 下(基于JDK8)
目录 概述 内部字段及构造方法 哈希值与索引计算 存储元素 扩容 删除元素 查找元素 总结 概述 在上文我们基于JDK7分析了HashMap的实现源码,介绍了HashMap的加载因子loadFac ...
- Akka源码分析-ask模式
在我之前的博文中,已经介绍过要慎用Actor的ask.这里我们要分析一下ask的源码,看看它究竟是怎么实现的. 开发时,如果要使用ask方法,必须要引入akka.pattern._,这样才能使用ask ...
- tp5底层源码分析之------tp5.1类的自动加载机制
tp框架作为国内主流框架,目前已经发布了6.0版本,相当于3.*版本是进行了重构,今天我们从源码的角度来研究下tp5.1自动加载的实现 作为单入口框架,从入口文件看起,入口文件在public/下,那么 ...
- JVM源码分析之JDK8下的僵尸(无法回收)类加载器[z]
[z]http://lovestblog.cn/blog/2016/04/24/classloader-unload/ 概述 这篇文章基于最近在排查的一个问题,花了我们团队不少时间来排查这个问题,现象 ...
- 个人从源码理解JIT模式下angular编译AppModule的过程
承接上文.笔者之前将一个angular项目的启动过程分为了两步: 创建平台得到 PlatformRef ,以及执行平台引用提供的方法编译根模块 AppModule .本文就将着眼于创建好的平台,从an ...
- nginx源码分析-源码结构
本文主要简单介绍nginx源码目录结构.程序编译流程.如何构建学习nginx的环境等.本文以及后续nginx源码分析文章是基于nginx当前(2009-02-27)的稳定版本0.6.35进行的分析,该 ...
随机推荐
- 【翻译】Flink Table Api & SQL —— 数据类型
本文翻译自官网:https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/types.html Flink Table ...
- [LeetCode] 260. Single Number III 单独数 III
Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...
- 解决ScrollView嵌套百度地图滑动冲突
一.问题描述 scrollview中嵌套百度地图时会出现滑动冲突,地图无法滑动的情况. 二.期望结果 焦点在地图上时,只有地图移动,焦点在地图外部时,可以滑动scrollview. 三.解决方法 自定 ...
- Jenkins+TestNG+gitlab+maven持续集成
准备工作: 1.安装Jenkins 网上有jenkins安装配置教程 2.jenkins配置 2.1全局工具配置 配置JDK JDK别名:名称可以随意,但是要方便识别 JAVA_HOME:centos ...
- php_mvc实现步骤三,四
3.match_mvc MVC 以ecshop的前台为例: 功能一: 首页 购物车数据,商品分类数据,其他的首页需要的数据 功能二: 拍卖活动 购物车数据,商品分类数据,拍卖相关数据 功能三: 团购商 ...
- 看看这5个最容易犯的Java错误,你犯了没?
人非圣贤,孰能无过.都说Java语言是一门简单的编程语言,基于C++演化而来,剔除了很多C++中的复杂特性,但这并不能保证Java程序员不会犯错.那么对于广大的Java程序员来说,它们最容易犯的几个错 ...
- list<Integer>,Integer[],int[]之间的互转(jdk1.8)
偶然在开发过程中需要将int[] 转成 List<Integer>,采用了遍历的方式,写的代码实在太多. List<Integer> list = new ArrayList& ...
- Python基础学习:字符串认知与应用
一.len() 家电维修 len:全写是length,是计算容量的函数:例如a="1234",len(a)=4 如果是中文字符,比如a="哈",len(a)= ...
- Ubuntu下载搜狗输入法
实在...因为百度上写的就很好了,所以这里就直接“链”了.. https://jingyan.baidu.com/article/2d5afd6933a67b85a2e28e9f.html
- Dubbo学习摘录(二)
扩展点机制 扩展点的配置 (1)根据关键字读取配置,获取具体的实现类 比如在 dubbo-demo-provider.xml 文件中配置: 则会根据rmi去读取具体的协议实现类RmiProtocol. ...