Nginx 子目录应用URI重写与参数传递教程

31次阅读

Nginx 子目录应用URI重写与参数传递教程

本教程详细阐述了如何在Nginx中为PHP应用实现子目录URI重写,特别是如何从请求URI中剥离子目录路径并将其余部分作为参数传递给主入口文件。通过try_files和rewrite指令的组合,本教程提供了一种高效且准确的解决方案,以替代Apache .htaccess的RewriteRule功能,确保URL的整洁性和应用的正确路由

场景描述

在web开发中,我们经常会将php应用部署在web服务器的某个子目录下,例如 /shop。为了实现友好的url(clean urls)和路由功能,我们通常希望将类似 example.com/shop/product/123 的请求内部重写为 example.com/shop/main.php?route=/product/123,其中 /product/123 是动态路由参数。在apache服务器中,这通常通过 .htaccess 文件中的 rewriterule 实现,例如:

RewriteCond %{REQUEST_URI} !.(ico|jpg|png|img)$  RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) main.php?route=$1

然而,在Nginx环境中,直接照搬Apache的重写规则并不适用,需要采用Nginx特有的配置方式来实现相同的效果。

Nginx 重写挑战与解决方案

Nginx中的try_files指令主要用于检查文件或目录是否存在,并按顺序尝试提供它们,如果都找不到则执行最后一个参数(通常是内部重定向或返回错误)。而rewrite指令则用于基于正则表达式匹配来修改URI。

尝试使用try_files $uri $uri/ /shop/main.php?route=$uri; 的方式会导致 $uri 变量包含完整的请求路径(如 /shop/product/123),这并不是我们想要的路由参数。我们目标是剥离 /shop 部分,只保留 /product/123。

正确的解决方案是结合使用 location 块、try_files 和 rewrite 指令,并利用正则表达式的捕获组功能来精确提取所需路径。

Nginx 配置详解

以下是实现上述URI重写功能的Nginx配置示例:

Nginx 子目录应用URI重写与参数传递教程

降重鸟

要想效果好,就用降重鸟。AI改写智能降低AIGC率和重复率。

Nginx 子目录应用URI重写与参数传递教程113

查看详情 Nginx 子目录应用URI重写与参数传递教程

server {     listen 80;     server_name example.com;     root /var/www/html; # 您的网站根目录      index index.php index.html index.htm;      # PHP-FPM 配置,确保您的PHP应用能够正常解析     location ~ .php$ {         try_files $uri =404;         fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # 根据您的PHP版本和配置调整         fastcgi_index index.php;         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;         include fastcgi_params;     }      # 处理 /shop 子目录下的请求     location /shop/ {         # 尝试查找静态文件或目录,如果不存在,则内部重定向到 @rewrite 命名location         try_files $uri $uri/ @rewrite;     }      # 命名location,用于执行URI重写     location @rewrite {         # 使用rewrite指令进行URI重写         # ^/shop(/.*) 匹配以 /shop/ 开头的URI,并捕获 / 后面的所有内容到 $1         # /shop/main.php?route=$1 将URI重写为指向 main.php 并传递捕获的路由参数         # last 标志停止当前请求的处理,并启动一个新的URI匹配过程,使用重写后的URI         rewrite ^/shop(/.*) /shop/main.php?route=$1 last;     }      # 阻止访问隐藏文件     location ~ /. {         deny all;     } }

配置解析:

  1. location /shop/ { … }:

    • 这个location块匹配所有以 /shop/ 开头的请求URI。
    • try_files $uri $uri/ @rewrite;:这是Nginx处理请求的第一个尝试。
      • $uri: 尝试查找与请求URI完全匹配的文件(例如 /var/www/html/shop/product/123)。
      • $uri/: 如果文件不存在,尝试查找与请求URI对应的目录并提供其默认索引文件(例如 /var/www/html/shop/product/123/index.php)。
      • @rewrite: 如果以上两种尝试都失败,Nginx将内部重定向到名为 @rewrite 的命名location块。
  2. location @rewrite { … }:

    • 这是一个命名location,它不会直接匹配传入的URI,而是作为try_files或error_page的后备处理机制。
    • rewrite ^/shop(/.*) /shop/main.php?route=$1 last;:这是核心的重写逻辑。
      • rewrite: Nginx的重写指令。
      • ^/shop(/.*): 这是一个正则表达式。
        • ^: 匹配URI的开头。
        • /shop: 匹配字面字符串 /shop。
        • (/.*): 这是一个捕获组。它匹配 / 后面的任意字符(.)零次或多次(*)。捕获到的内容会被存储在 $1 变量中。例如,对于 /shop/product/123,$1 将是 /product/123。
      • /shop/main.php?route=$1: 这是重写后的目标URI。它将原始请求重写为指向 main.php,并将捕获组 $1 的内容作为 route 参数传递。
      • last: 这是一个标志。它告诉Nginx停止当前location块的处理,并用重写后的新URI(/shop/main.php?route=/product/123)重新开始匹配location块。这意味着Nginx会再次查找匹配 /shop/main.php 的location块,最终由PHP-FPM处理。

注意事项

  • last 标志的重要性: last 标志在 rewrite 指令中至关重要。它确保Nginx在重写URI后重新进行location匹配,从而使重写后的URI能够被正确的PHP-FPM处理location块(location ~ .php$)捕获并执行。如果没有last,Nginx可能不会重新处理重写后的URI,导致意外行为。
  • 避免冗余的 try_files: 避免在@rewrite这样的命名location中再次使用try_files,因为它会增加不必要的系统调用(如stat),降低性能。rewrite指令本身就是用来转换URI的。
  • PHP-FPM 配置: 确保您的Nginx配置中包含正确的PHP-FPM处理块(通常是 location ~ .php$),以便能够正确解析 main.php 文件。
  • 静态文件处理: try_files指令的优势在于,如果请求的URI对应一个实际存在的静态文件(例如 /shop/css/style.css),Nginx会直接提供该文件,而不会触发重写规则,这有助于提高性能。
  • 测试: 在生产环境部署之前,务必在开发或测试环境中充分测试您的Nginx配置,确保所有预期的URL重写都能正常工作。可以使用 curl -I example.com/shop/product/123 等命令检查HTTP响应头。

总结

通过巧妙地结合Nginx的location、try_files和rewrite指令,我们可以高效且精确地实现复杂的URI重写逻辑,例如从子目录URI中剥离特定路径并作为参数传递。这种方法不仅能够完美替代Apache的RewriteRule功能,还能利用Nginx的强大性能优势,为PHP应用提供整洁、友好的URL结构。理解rewrite指令中的正则表达式捕获组和last标志是掌握Nginx重写功能,解决类似路由问题的关键。

以上就是Nginx 子目录应用URI重写与参数传递教程的详细内容,更多请关注css php html 正则表达式 php7 apache nginx access curl ai unix 路由 php nginx css 正则表达式 html cURL 字符串 var location apache http

css php html 正则表达式 php7 apache nginx access curl ai unix 路由 php nginx css 正则表达式 html cURL 字符串 var location apache http

text=ZqhQzanResources