nginx try_files流程解析

前端部署单页应用时在nginx上经常用到try_files指令,而对于try_files并不知道其所以然,所以花时间整理总结如下。

Syntax: try_files file … uri;
try_files file … =code;
Default: —
Context: server, location

根据root和alias指令提供的值按照try_files指令值的顺序查找对应文件是否存在。可以通过以斜杠结(/)尾的文件名让try_files查找文件夹是否存在(例如:“$uri/”)。try_files指令提供的file都不存在那么就会发起内部重定向到uri。如果可以找到file,以找到的第一个file作为条件继续处理当前请求。

上面的描述没有错,但是不够具体,刚看这个描述我有如下问题:

  1. 对于file和uri,try_files的处理有什么不同?
  2. try_files的处理流程在nginx中具体是什么样的?
  3. 查找到文件和文件之后呢?
  4. 什么是内部重定向?

准备工作

  1. 开启nginx的debug模式
  • 确保 nginx -V 输出有 configure arguments: --with-debug。如果没有需要重新编译安装ngxin,具体方法借助搜索引擎吧。

  • 在http模块下添加配置:

      http {# 设置错误日志地址和日志级别为debugerror_log path/to/log/file debug;}
    
  1. 准备验证环境
  • 准备网站根目录 /path/to/www/
  • 添加测试nginx服务:
    server {listen 8080;root /path/to/www/;location / {try_files /helloworld.html /hello/ /internalRedirect;}location /internalRedirect {return 200 "internalRedirect";}
    }
    
  1. 准备知识
    nginx 配置文件执行是分为11个阶段按照顺序执行的,try_files流程涉及到的阶段有find-config、try_files和content这三个阶段,server-rewrite、rewrite、post-write等剩余阶段此处省略。

    find-config阶段主要根据请求的uri在nginx文件中寻找匹配的location块。

    try_files阶段主要执行try_files指令。

    content阶段上面的nginx服务只涉及到默认的模块,nginx_index、nginx_autoindex和nginx_static。

try_files指令解析

  1. 当请求匹配中 location / 时,try_files会去找文件 /path/to/www/helloworld.html没找到会继续找/path/to/www/hello文件夹,都没找到,最后会内部重定向到 /internalRedirect。

    curl http://localhost:8080/
    

    返回:

    internalRedirect
    

    截取部分debug日志文件。

    [debug] 17945#0: *2 trying to use file: "/helloworld.html" "/path/to/www/helloworld.html"
    [debug] 17945#0: *2 trying to use dir: "/hello" "/path/to/www/hello"
    [debug] 17945#0: *2 trying to use file: "/internalRedirect" "/path/to/www/internalRedirect"
    [debug] 17945#0: *2 internal redirect: "/internalRedirect?"
    [debug] 17945#0: *2 rewrite phase: 1
    [debug] 17945#0: *2 test location: "/"
    [debug] 17945#0: *2 test location: "internalRedirect"
    [debug] 17945#0: *2 using configuration "/internalRedirect"
    

    nginx执行顺序是先执行findConfig匹配和$uri合适location块配置,才会执行try_files指令,当try_files使用内部重定向的时候,请求的处理流程会被回退到findConfig阶段重新使用/internalRedirect重新匹配location。这个重定向和外部重定向http的301不一样,它并不会引起浏览器地址栏的url的修改,所以被称为内部重定向

  2. 当找到 /helloworld 之后try_files指令会重写uri的值,当执行到content阶段后会依据新的uri的值,当执行到content阶段后会依据新的uricontenturi值获取对应的静态文件。

  • 在/path/to/www/文件夹下添加helloworld.html文件,其内容是hello world。

  • 在ngxin配置中添加
    add_header header_uri $uri;

    curl -i http://localhost:8080/  # -i 会展示响应头
    

    返回:

    HTTP/1.1 200 OK
    ...
    header_uri: /helloworld.htmlhello world
    

    截取部分log文件日志:

    [debug] 18875#0: *1 trying to use file: "/helloworld.html" "/path/to/www/helloworld.html"
    [debug] 18875#0: *1 try file uri: "/helloworld.html"
    ...
    [debug] 18875#0: *1 http filename: "/path/to/www/helloworld.html"
    
  1. 当文件夹hello存在,try_file会将$uri修改为 /hello 接着给content阶段的模块处理。
  • 删除上一步骤的helloworld.html文件。

    curl -i http://localhost:8080/  # -i 会展示响应头
    

    返回:

    HTTP/1.1 301 Moved Permanently
    ...
    header_uri: /hello<html>
    <head><title>301 Moved Permanently</title></head>
    <body>
    <center><h1>301 Moved Permanently</h1></center>
    <hr><center>nginx/1.23.0</center>
    </body>
    </html>
    

    截取部分log文件日志:

    [debug] 18875#0: *2 trying to use file: "/helloworld.html" "/Users/zhou/nginx_web/helloworld.html"
    [debug] 18875#0: *2 trying to use dir: "/hello" "/Users/zhou/nginx_web/hello"
    [debug] 18875#0: *2 try file uri: "/hello"
    [debug] 18875#0: *2 http filename: "/Users/zhou/nginx_web/hello"
    [debug] 18875#0: *2 http static fd: -1
    [debug] 18875#0: *2 http dir
    [debug] 18875#0: *2 http finalize request: 301, "/hello?" a:1, c:1
    

    为什么try_files寻找文件夹的时候需要把指令值/hello/改成/hello?我理解末尾的斜杠只是表示try_files这个名字是一个文件夹名,所以找的时候把末尾的斜杠去掉了,如果想要$uri被赋值的时候带上末尾的斜杠可以 try_files /helloworld.html /hello// /internalRedirect,可以给他多加一个斜杠。

参考

agentzh 的 Nginx 教程(版本 2020.03.19)

Nginx文档try_files指令

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

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

相关文章

javascript中编码与解码的decodeURI()、decodeURIComponent()区别

1、 定义和用法 decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码。decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码。 从W3C的定义和用法来看&#xff0c;两者没有什么区别&#xff0c;但是两者的参数是有区别的&#xff1a;decodeU…

vb 类模拟 引用

引用&#xff1a;http://wenku.baidu.com/view/f434ea26a5e9856a56126008.html Class1中 Option Explicit Public Sub test() Form1.TextForIpAddressAdd.Text "123"End Sub Form1中 Option Explicit Private test As New Class1 Private Sub Form_Load() 初始化 te…

用js来实现那些数据结构12(散列表)

上一篇写了如何实现简单的Map结构&#xff0c;因为东西太少了不让上首页。好吧。。。 这一篇文章说一下散列表hashMap的实现。那么为什么要使用hashMap&#xff1f;hashMap又有什么优势呢&#xff1f;hashMap是如何检索数据的&#xff1f;我们一点一点的来解答。 在我们学习一门…

如何自定义Hibernate脏检查机制

介绍 在上一篇文章中&#xff0c;我描述了Hibernate自动脏检查机制。 尽管您应该始终喜欢它&#xff0c;但是有时您可能想添加自己的自定义污垢检测策略。 自定义脏检查策略 Hibernate提供以下定制机制&#xff1a; 休眠拦截器#findDirty&#xff08;&#xff09; CustomEnt…

读vue【深入响应式系统】后整理

一直以来对vue的依赖自动追踪的原理很感兴趣&#xff0c;像魔法一样。对于交给vue的对象返回后&#xff0c;在哪里使用了这个返回的对象vue会自动追踪&#xff0c;等这个对象改变时vue会自动通知到之前使用改变量的方法&#xff0c;整个过程和react很不一样&#xff0c;react的…

萌新自我介绍

第一次用博客&#xff0c;多有不会&#xff0c;可能向各位大佬请教&#xff0c;谢谢&#xff01;&#xff01;&#xff01;&#xff01;转载于:https://www.cnblogs.com/fakerOrz/p/11194872.html

使用select一个表更新另一个表(批量更新)

update a set a2b.b2, a3b.b3, ... from b where a.a1b.b1 转载于:https://www.cnblogs.com/haver/articles/2244740.html

用js来实现那些数据结构06(队列)

其实队列跟栈有很多相似的地方&#xff0c;包括其中的一些方法和使用方式&#xff0c;只是队列使用了与栈完全不同的原则&#xff0c;栈是后进先出原则&#xff0c;而队列是先进先出&#xff08;First In First Out&#xff09;。 一、队列 队列是一种特殊的线性表&#xff0c…

探索SwitchYard 2.0.0.Alpha2快速入门

在我的最后一篇文章中&#xff0c;我解释了如何在WildFly 8.1上使用SwitchYard。 同时&#xff0c;该项目很忙&#xff0c;并发布了另一个Alpha2。 这是一个很好的机会&#xff0c;在这里浏览快速入门并刷新您的记忆。 除了版本更改之外&#xff0c;您仍然可以使用较早的博客来…

MySQL之触发器

二&#xff1a;触发器 1. 什么是触发器 触发器&#xff0c;是一段与某个表相关的sql语句&#xff0c;会在某个时间点&#xff0c;满足某个条件后自动触发执行 其中两个关键因素&#xff1a; 时间点 * 事件发生前&#xff0c;before|事件发生后 after事件 * update delete inser…

PowerDesigner使用技巧

PowerDesigner使用MySQL的auto_increment   ◇问题描述&#xff1a;   PD怎样能使主键id使用MySQL的auto_increment呢&#xff1f; ◇解决方法&#xff1a;    打开table properties窗口 → columns → 选中id列 → 打开columns properties窗口 → 勾选identity即可   …

走进webpack(1)--环境拆分及模块化

初级的文章和demo已经基本完成了&#xff0c;代码也已经上传到了我的github上&#xff0c;如果你对webpack的使用并不是十分了解&#xff0c;那么建议你回头看下走近系列&#xff0c;里面包括了当前项目中使用频繁的插件&#xff0c;loader的讲解。以及基本的webpack配置&#…

适用于微服务架构的Apache Camel

在知道微服务架构被称为之前&#xff0c;我一直在使用它们。 我曾经使用过由隔离模块组成的管道应用程序&#xff0c;这些模块通过队列相互交互。 从那时起&#xff0c;许多&#xff08;前&#xff09;ThoughtWorks专家讨论了微服务。 首先是 Fred George&#xff0c; 然后是 J…

题解 P3811 【【模板】乘法逆元】

P3811 【模板】乘法逆元 一个刚学数论的萌新&#xff0c;总结了一下这题的大部分做法 //一、费马小定理快速幂 O(nlogn) 64分 #include<cstdio> using namespace std; typedef long long ll; int a,b; inline ll pow(ll x,ll p) {ll ans1;x%b;while(p) {if (p&1) an…

QueryString加密

有些人不想由URL暴露一些訊息&#xff0c;除了可以使用URL Rewrite之外&#xff0c;其實簡便一點的方法還有使用編碼or加密來達到偽裝的目的。使用Base64的原因是因為他的編碼不會有難以接受的特殊字元(註1)&#xff0c;你也可以用其他的編碼or加密算法替代(註2)。其實這邊已經…

即时大数据流处理=即时风暴

在Ubuntu背后的公司Canonical&#xff0c;每6个月进行一次技术工作&#xff0c;以第一手测试我们的工具并向其他人展示新想法。 这次&#xff0c;我创建了一个即时大数据解决方案&#xff0c;更具体地讲是“即时风暴”。 Storm现在是Apache基金会的一部分&#xff0c;但以前St…

webstorm中vue项目--运行配制

## npm搭建的项目&#xff0c;需要运行npm run dev来启动 webstorm作为一款优秀的编辑器&#xff0c;通过配置运行设置&#xff0c;达到一键运行 1.添加node.js配置 2.configuration->node interpreter : 路径/node.exe 3.configuration->working directory&#xff1a; …

VS2010 自动化整理代码(1)--- VS正则表达替换 PK Vim

自从开始在VS2010的IDE中开始用正则表达式修改 最近为了给Fortran找个好一点的编辑器&#xff0c;又开始使用Vim了。Vim是久负盛名的编辑器之神&#xff0c;可我们习惯了Visual Studio的智能提示等方便的操作&#xff0c;就总在琢磨要是VS 1. VS正则表达替换 PK Vim 这是善用…

Java基础(多态的理解与应用)

1.多态概述 多态是继封装、继承之后&#xff0c;面向对象的第三大特性。 多态现实意义理解&#xff1a; 现实事物经常会体现出多种形态&#xff0c;如学生&#xff0c;学生是人的一种&#xff0c;则一个具体的同学张三既是学生也是人&#xff0c;即出现两种形态。 …

Java并发教程–锁定:内在锁

在以前的文章中&#xff0c;我们回顾了在不同线程之间共享数据的一些主要风险&#xff08;例如原子性和可见性 &#xff09;以及如何设计类以安全地共享&#xff08; 线程安全的设计 &#xff09;。 但是&#xff0c;在许多情况下&#xff0c;我们将需要共享可变数据&#xff0…