Nginx 配置指令的执行顺序(六)

简介: 前面我们在 (五) 中提到,在一个 location 中使用 content 阶段指令时,通常情况下就是对应的 Nginx 模块注册该 location 中的“内容处理程序”。那么当一个 location 中未使用任何 content 阶段的指令,即没有模块注册“内容处理程序”时,content 阶段会发生什么事情呢?谁又来担负起生成内容和输出响应的重担呢?答案就是那些把当前请求的 URI 映射到文件系统的静态资源服务模块。

前面我们在 (五) 中提到,在一个 location 中使用 content 阶段指令时,通常情况下就是对应的 Nginx 模块注册该 location 中的“内容处理程序”。那么当一个 location 中未使用任何 content 阶段的指令,即没有模块注册“内容处理程序”时,content 阶段会发生什么事情呢?谁又来担负起生成内容和输出响应的重担呢?答案就是那些把当前请求的 URI 映射到文件系统的静态资源服务模块。当存在“内容处理程序”时,这些静态资源服务模块并不会起作用;反之,请求的处理权就会自动落到这些模块上。

 

    Nginx 一般会在 content 阶段安排三个这样的静态资源服务模块(除非你的 Nginx 在构造时显式禁用了这三个模块中的一个或者多个,又或者启用了这种类型的其他模块)。按照它们在 content 阶段的运行顺序,依次是 ngx_index 模块,ngx_autoindex 模块,以及 ngx_static 模块。下面就来逐一介绍一下这三个模块。

 

    ngx_index 和 ngx_autoindex 模块都只会作用于那些 URI 以 / 结尾的请求,例如请求 GET /cats/,而对于不以 / 结尾的请求则会直接忽略,同时把处理权移交给 content 阶段的下一个模块。而 ngx_static 模块则刚好相反,直接忽略那些 URI 以 / 结尾的请求。

 

    ngx_index 模块主要用于在文件系统目录中自动查找指定的首页文件,类似 index.html 和 index.htm 这样的,例如:

    location / {
        root /var/www/;
        index index.htm index.html;
    }

这样,当用户请求 / 地址时,Nginx 就会自动在 root 配置指令指定的文件系统目录下依次寻找 index.htm 和index.html 这两个文件。如果 index.htm 文件存在,则直接发起“内部跳转”到 /index.htm 这个新的地址;而如果 index.htm 文件不存在,则继续检查 index.html 是否存在。如果存在,同样发起“内部跳转”到/index.html;如果 index.html 文件仍然不存在,则放弃处理权给 content 阶段的下一个模块。

 

    我们前面已经在 Nginx 变量漫谈(二) 中提到, echo_exec 指令和 rewrite 指令可以发起“内部跳转”。这种跳转会自动修改当前请求的 URI,并且重新匹配与之对应的 location 配置块,再重新执行rewriteaccesscontent 等处理阶段。因为是“内部跳转”,所以有别于 HTTP 协议中定义的基于 302 和 301 响应的“外部跳转”,最终用户的浏览器的地址栏也不会发生变化,依然是原来的 URI 位置。而ngx_index 模块一旦找到了 index 指令中列举的文件之后,就会发起这样的“内部跳转”,仿佛用户是直接请求的这个文件所对应的 URI 一样。

 

    为了进一步确认 ngx_index 模块在找到文件时的“内部跳转”行为,我们不妨设计下面这个小例子:

    location / {
        root /var/www/;
        index index.html;
    }
 
    location /index.html {
        set $a 32;
        echo "a = $a";
    }

此时我们在本机的 /var/www/ 目录下创建一个空白的 index.html 文件,并确保该文件的权限设置对于运行 Nginx worker 进程的帐户可读。然后我们来请求一下根位置(/):

    $ curl 'http://localhost:8080/'
    a = 32

这里发生了什么?为什么输出不是 index.html 文件的内容(即空白)?首先对于用户的原始请求 GET /,Nginx 匹配出 location / 来处理它,然后 content 阶段的 ngx_index 模块在 /var/www/ 下找到了index.html,于是立即发起一个到 /index.html 位置的“内部跳转”。

 

    到这里,相信大家都不会有问题。接下来有趣的事情发生了!在重新为 /index.html 这个新位置匹配location 配置块时,location /index.html 的优先级要高于 location /,因为 location 块按照 URI 前缀来匹配时遵循所谓的“最长子串匹配语义”。这样,在进入 location /index.html 配置块之后,又重新开始执行rewrite 、access、以及 content 等阶段。最终输出 a = 32 自然也就在情理之中了。

 

    我们接着研究上面这个例子。如果此时把 /var/www/index.html 文件删除,再访问 / 又会发生什么事情呢?答案是返回 403 Forbidden 出错页。为什么呢?因为 ngx_index 模块找不到 index 指令指定的文件(在这里就是 index.html),接着把处理权转给 content 阶段的后续模块,而后续的模块也都无法处理这个请求,于是 Nginx 只好放弃,输出了错误页,并且在 Nginx 错误日志中留下了类似这一行信息:

    [error] 28789#0: *1 directory index of "/var/www/" is forbidden

所谓 directory index 便是生成“目录索引”的意思,典型的方式就是生成一个网页,上面列举出 /var/www/目录下的所有文件和子目录。而运行在 ngx_index 模块之后的 ngx_autoindex 模块就可以用于自动生成这样的“目录索引”网页。我们来把上例修改一下:

    location / {
        root /var/www/;
        index index.html;
        autoindex on;
    }

此时仍然保持文件系统中的 /var/www/index.html 文件不存在。我们再访问 / 位置时,就会得到一张漂亮的网页:

    $ curl 'http://localhost:8080/'
    <html>
    <head><title>Index of /</title></head>
    <body bgcolor="white">
    <h1>Index of /</h1><hr><pre><a href="../">../</a>
    <a href="cgi-bin/">cgi-bin/</a>  08-Mar-2010 19:36   -
    <a href="error/">error/</a>      08-Mar-2010 19:36   -
    <a href="htdocs/">htdocs/</a>    05-Apr-2010 03:55   -
    <a href="icons/">icons/</a>      08-Mar-2010 19:36   -
    </pre><hr></body>
    </html>

生成的 HTML 源码显示,我本机的 /var/www/ 目录下还有 cgi-bin/error/htdocs/, 以及 icons/ 这几个子目录。在你的系统中尝试上面的例子,输出很可能会不太一样。

 

    值得一提的是,当你的文件系统中存在 /var/www/index.html 时,优先运行的 ngx_index 模块就会发起“内部跳转”,根本轮不到 ngx_autoindex 执行。感兴趣的读者可以自己测试一下。

 

    在 content 阶段默认“垫底”的最后一个模块便是极为常用的 ngx_static 模块。这个模块主要实现服务静态文件的功能。比方说,一个网站的静态资源,包括静态 .html 文件、静态 .css 文件、静态 .js 文件、以及静态图片文件等等,全部可以通过这个模块对外服务。前面介绍的 ngx_index 模块虽然可以在指定的首页文件存在时发起“内部跳转”,但真正把相应的首页文件服务出去(即把该文件的内容作为响应体数据输出,并设置相应的响应头),还是得靠这个 ngx_static 模块来完成。

目录
打赏
0
0
0
0
94
分享
相关文章
Nginx中配置HTTP2协议的方法
Nginx中配置HTTP2协议的方法
323 7
Nginx进程配置指令详解
Nginx进程配置指令主要包括:`worker_processes`设置工作进程数;`worker_cpu_affinity`绑定CPU核心;`worker_rlimit_nofile`设置最大文件描述符数量;`worker_priority`设置进程优先级;`worker_connections`设置最大连接数;`daemon`控制守护进程模式;`master_process`启用主进程模式;`pid`设置PID文件路径;`user`指定用户和组;`error_log`配置错误日志。这些指令在`nginx.conf`中配置,用于优化和控制Nginx的运行行为。
90 10
Nginx的location配置详解
【10月更文挑战第16天】Nginx的location配置详解
Nginx常用基本配置总结:从入门到实战的全方位指南
Nginx常用基本配置总结:从入门到实战的全方位指南
657 0
nginx配置证书和私钥进行SSL通信验证
nginx配置证书和私钥进行SSL通信验证
159 4
配置Nginx反向代理时如何指定后端服务器的权重?
配置Nginx反向代理时如何指定后端服务器的权重?
313 61
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
344 60
配置Nginx反向代理实现SSL加密访问的步骤是什么?
我们可以成功地配置 Nginx 反向代理实现 SSL 加密访问,为用户提供更安全、可靠的网络服务。同时,在实际应用中,还需要根据具体情况进行进一步的优化和调整,以满足不同的需求。SSL 加密是网络安全的重要保障,合理配置和维护是确保系统安全稳定运行的关键。
430 60
nginx反向代理bucket目录配置
该配置实现通过Nginx代理访问阿里云OSS存储桶中的图片资源。当用户访问代理域名下的图片URL(如 `http://代理域名/123.png`)时,Nginx会将请求转发到指定的OSS存储桶地址,并重写路径为 `/prod/files/2024/12/12/123.png`。
191 5
如何配置Nginx反向代理以实现负载均衡?
如何配置Nginx反向代理以实现负载均衡?
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等