Nginx 下禅道的伪静态 rewrite 规则

发布于 2024-02-17 09:04:28 字数 4459 浏览 32 评论 0

搭建了一个禅道的项目管理平台,但是 Nginx 下并不是伪静态的,URL 看着不是很舒服,上网搜索配置规则,但是没有一个可以正常使用的,于是乎自己琢磨一下。

先给出最终配置,有兴趣看原因的可以往下看

server {
    listen 80;
    root /zentao/root/path/www;
    index index.php index.html index.htm;
    server_name domain_name;

    location / {
        try_files $uri /index.php$uri;
    }

    location ~ \.php(/.+)?$ {
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    access_log off;
}

禅道给出了 apache 的伪静态规则,但是我尝试了半天也没有转换成可用的 nginx 伪静态规则,但是禅道是基于 PHP 的,而 PHP 伪静态一般基于 $_SERVER 变量中的一些变量来实现的,既然 apache 可以实现伪静态,那么就打印一下伪静态后的 $_SERVER 变量的值。

修改禅道根目录下 www/index.php 文件,在最上面修改为如下代码:

<?php
echo "<pre>";
print_r($_SERVER);
echo "</pre>";
die;

然后访问 http://domain/user-login-Lw==.html 此为禅道登陆 url

// 仅给出几个重要的变量
Array
(
[REDIRECT_URL] => /user-login-Lw==.html
[REQUEST_URI] => /user-login-Lw==.html
[SCRIPT_NAME] => /index.php
[PATH_INFO] => /user-login-Lw==.html
[PATH_TRANSLATED] => redirect:/index.php/user-login-Lw==.html
[PHP_SELF] => /index.php/user-login-Lw==.html
)

对于未配置过的 nginx 做相同的操作:

未配置的 nginx 并不是什么都没配置,基本的还是要配置的

location / {
try_files $uri /index.php;
}
location ~ \.php$ {
# With php5-fpm:
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}

如上,这两个 location 还是要有的,一个是将所有的请求重定向到 index.php ,一个是解析 php 文件的.

这次,php 返回的信息为

// 仅给出几个重要的变量
Array
(
[SCRIPT_NAME] => /index.php
[REQUEST_URI] => /user-login-Lw==.html
[DOCUMENT_URI] => /index.php
[PHP_SELF] => /index.php
)

对比一下,发现不同了吧。nginx 少了 PATH_INFO ,而且 PHP_SELF 也是不一样的,至于 REDIRECT_URLPATH_TRANSLATED 这些变量都是 apache 自己加的,禅道并不会用到。

回想一下禅道的配置文件 config/config.phpconfig/my.php 中有一项 $config->requestType 配置,如果配置为 GET 的话,就会禁用伪静态,而通过 query string 的方式,如果配置成 PATH_INFO 的话就需要 nginx 或 apache 配置伪静态规则,也就是说禅道通过解析 PATH_INFO 来实现伪静态的。

那么 PATH_INFO 又是什么东东,根据 PHP 官方文档 的解释,如果我访问 http://www.example.com/php/path_info.php/some/stuff?foo=bar 这个 url,那个 PATH_INFO 就应该等于 /some/stuff ​,也就是所 PATH_INFO 等于 url 中跟在真实脚本名称之后并且在查询语句(query string)之前的字符串,你可能会说,我访问的 url 中根本没有 filename.php 啊,那是因为 nginx 帮你添加了,记得配置中的 try_files $uri /index.php$uri 吧,这个内部跳转就是干这个事情的。

找到了原因就开始解决,Nginx 和 PHP 是通过 cgi 协议传递数据的,可以通过 nginx 开启 debug ( http://nginx.org/en/docs/debugging_log.html ) 来查看传递 nginx 和 php 交换的数据。

这里不给出详细 debug log 了,反正开启 log 后发现 nginx 并没有传递 PATH_INFO 给 php,于是在解析 php 的 location 中添加一行

location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
}

但只有这个还是不行,因为此时 nginx 内部变量 $uri (就相当于 PHP_SELF 的值) 还是*/index.php*,需要再修改一个地方

location / {
try_files $uri /index.php;
}

修改之后 php 那个 location 就没办法被识别了,需要修改为 \.php(/.+)?$

最终的效果就是

server {
    listen 80;
    root /zentao/root/path/www;
    index index.php index.html index.htm;
    server_name domain_name;

    location / {
        try_files $uri /index.php$uri;
    }

    location ~ \.php(/.+)?$ {
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    access_log off;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文