.htaccess - 递归地将斜杠映射到下划线(内部重定向)

Posted

技术标签:

【中文标题】.htaccess - 递归地将斜杠映射到下划线(内部重定向)【英文标题】:.htaccess - Recursively mapping slashes to underscores (internal redirect) 【发布时间】:2021-07-27 12:22:37 【问题描述】:

与上一个问题相关:.htaccess - Recursively mapping slashes to underscores

被列为“完整解决方案”的代码工作了 12 个月。然后停止工作。 .htaccess 代码也没有改变 - 只是为了让事情变得更难。

问题

谁能帮我实现期望的结果

期望的结果

获取 https://domain.com/this/is/mah/page/structure 并显示位于网站根目录中的文件 /this_is_mah_page_strucutre.php

当前的代码

以下是htaccess文件中的内容

<IfModule mod_negotiation.c>
Options -MultiViews
Options All -Indexes
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine on
    DirectorySlash off

    # Error Redirects
        ErrorDocument 404 /incs/404.php

        RewriteCond %REQUEST_FILENAME !-d
        RewriteCond %REQUEST_FILENAME !-f
        RewriteCond %REQUEST_FILENAME.php !-f
        RewriteRule ^ - [R=404,L]

    # remove .php
        RewriteCond %THE_REQUEST \s/+(.+?)\.php[\s?] [NC]
        RewriteRule ^ /%1 [R=302,NE,L]

        # map the .php extension
        RewriteRule ^([^.]+?)/?$ $1.php [L]

    # map the slashes to underscores
        # when there are more than one / then "recursively" replace it by _
        RewriteCond %REQUEST_FILENAME !-f
        RewriteCond %REQUEST_FILENAME !-d

# This next line appears to be the problem
        RewriteRule ^([^/]+)/([^/]+/.+)$ $1_$2 [N,DPI]


# This next section appears to be doubling up, but was originally meant to catch anything that missed the previous block
        # when there is only one / then replace it by _ and redirect
        RewriteCond %REQUEST_FILENAME !-f
        RewriteCond %REQUEST_FILENAME !-d
        RewriteRule ^([^/]+)/([^/]+)$ /$1_$2 [L]

</IfModule>

可能的问题

如前所述,RewriteRule ^([^/]+)/([^/]+/.+)$ $1_$2 [N,DPI] 似乎没有按预期工作。

如果https://htaccess.madewithlove.be/?share=9bd3c5a0-4002-4324-a82e-0065b7286f82 是可信的,那么发生的事情是 [N] 没有导致递归 (a) 我需要,并且 (b) 它曾经提供。

MadeWithLove 测试结果表明/this/is/mah/page/structure 正在变为/this_is/mah/page/structure

我已尝试重新调整 PCRE RegEx,@anubhava 也是如此 - 但无法使其正常工作。

服务器

服务器为 httpd 使用版本 2.4.37-30.module_el8.3.0+561+97fdbbcc,并在 CentOS 8 上运行。有问题的代码大约 5 个月前从 CentOS 7 迁移而来,直到最近 7 天它一直运行良好。

就 Apache 设置和 .htaccess 文件而言,过去两周内没有任何变化。

【问题讨论】:

您能否在 Apache conf 中使用此指令启用跟踪级别 RewriteLogLogLevel info rewrite:trace4 我愿意,但似乎我不需要 - 下面的两个答案都能实现我的目标。谢谢! 【参考方案1】:

这样吧:

<IfModule mod_negotiation.c>
Options All -Indexes -MukltiViews
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine on
    DirectorySlash off
    # Error Redirects
    ErrorDocument 404 /incs/404.php

    RewriteCond %REQUEST_FILENAME -d [OR]
    RewriteCond %REQUEST_FILENAME -f
    RewriteRule ^ - [L]

    # remove .php
    RewriteCond %THE_REQUEST \s/+(.+?)\.php[\s?] [NC]
    RewriteRule ^ /%1 [R=301,NE,L]

    # map the slashes to underscores
    # when there are more than one / then "recursively" replace it by _
    # This next line appears to be the problem
    RewriteRule ^([^/]+)/(.+)$ $1_$2 [N,DPI]

    # map the .php extension
    RewriteCond %DOCUMENT_ROOT/$1.php -f
    RewriteRule ^([^.]+?)/?$ $1.php [L]
</IfModule>

【讨论】:

我喜欢在继续之前过滤掉真实文件/文件夹的想法。我没有想到这一点——直到现在,我一直在按块过滤它们。你的要优雅得多。 哦。您是否认为“加倍”位是必需的,因为它正在搜索 / 之后的任何内容?我已经注释掉了,看起来还不错。当然,从逻辑上讲,它不是必需的。 如果过滤掉了真正的文件/文件夹规则,那么在每个规则之前不需要进一步检查。 我在谈论RewriteRule ^([^/]+)/([^/]+)$ $1_$2 [L] - 这就是注释掉的内容。是的,早点-d-f 是个好主意。 是的,该规则可以被注释掉【参考方案2】:

试试:

RewriteEngine On
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME !-d
RewriteCond %REQUEST_URI ^(.+)\/(.*)$
RewriteRule ^ %1_%2 [L]

所以,你的完整 htaccess 是:

<IfModule mod_negotiation.c>
Options -MultiViews
Options All -Indexes
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine on
    DirectorySlash off

    # Error Redirects
        ErrorDocument 404 /incs/404.php

        RewriteCond %REQUEST_FILENAME !-d
        RewriteCond %REQUEST_FILENAME !-f
        RewriteCond %REQUEST_FILENAME.php !-f
        RewriteRule ^ - [R=404,L]

    # remove .php
        RewriteCond %THE_REQUEST \s/+(.+?)\.php[\s?] [NC]
        RewriteRule ^ /%1 [R=302,NE,L]

        # map the .php extension
        RewriteRule ^([^.]+?)/?$ $1.php [L]

        RewriteCond %REQUEST_FILENAME !-f
        RewriteCond %REQUEST_FILENAME !-d
        RewriteCond %REQUEST_URI ^(.+)\/(.*)$
        RewriteRule ^ %1_%2 [L]

</IfModule>

【讨论】:

这也有效。如果有两个答案,我不确定什么适合我。由于上一个问题(发布答案,一年后)的帮助,我已将绿色对勾授予 @anubhava。 @Mark,你可以投票给我。并接受阿努巴瓦的。由你决定。

以上是关于.htaccess - 递归地将斜杠映射到下划线(内部重定向)的主要内容,如果未能解决你的问题,请参考以下文章

使用 .htaccess 删除尾部斜杠

使用 .htaccess 重定向 404 而不重定向尾部斜杠

如何使用 .htaccess 正确地将 HTTP 301 重定向到 HTTPS?

在.htaccess中将ID重写为斜杠

Htaccess:从URL添加/删除尾部斜杠

.htaccess RewriteRule 用于在 javascript 中作为非斜杠添加的多个参数