【问题标题】:Apache2 rewrite returns filename extensionApache2 重写返回文件扩展名
【发布时间】:2022-01-21 06:56:52
【问题描述】:

我真的不明白我在哪里做错了。我正在尝试将规则应用于

http://localhost/prezzo/account/1

所以它被重写为

http://localhost/prezzo/account/test.php?user=1

我使用 UniformServer 作为 WAMP。我使用以下规则将 .htaccess 文件放在我正在处理的子文件夹 (prezzo/account/) 中:

RewriteEngine On
RewriteRule (\w+)/?$ test.php?user=$1 [L]

htaccess tester 报告规则已正确应用。

但是当我转到 URL http://localhost/prezzo/account/1test.php 时,它只包含了

<?php
    echo $_GET['user'];
?>

它返回字符串“php”而不是“1”。

如果我尝试

RewriteRule ^prezzo/account/(\w+)/?$ prezzo/account/test.php?user=$1 [L]

我得到 404 not found 尽管htaccess tester 报告该规则已正确应用并且 URL 被重写为

http://localhost/prezzo/account/test.php?user=1

如果我在地址栏中复制/粘贴它就可以了。

【问题讨论】:

    标签: mod-rewrite apache2


    【解决方案1】:

    但是当我转到 URL http://localhost/prezzo/account/1 并加载 test.php [...] 时,它返回字符串“php”而不是“1”。

    是的,这是所发布的规则所期望的。

    这似乎在“htaccess 测试器”中工作,因为该工具只对文件进行一次传递,这不是真实服务器的工作方式。

    RewriteRule (\w+)/?$ test.php?user=$1 [L]
    

    当您请求/prezzo/account/1 时...

    1. 请求被重写为test.php?user=1
    2. L 标志使重写引擎使用重写后的 URL (test.php?user=1) 作为下一轮处理的输入重新开始。
    3. 请求被重写为test.php?user=php,因为正则表达式(\w+)/?$ 捕获了test.phpphp 部分。 (\w 速记字符类不包括点且正则表达式未锚定。)
    4. L 标志使重写引擎使用重写的 URL (test.php?user=php) 作为下一轮处理的输入重新开始。
    5. 请求被重写为test.php?user=php(再次)。
    6. 由于 URL 未更改通过,重写过程停止,请求最终被重写为 /test.php?user=php

    解决方案 A - 使用 END 标志

    一种解决方案是简单地使用END 标志(Apache 2.4)而不是L 来防止重写引擎“循环”。一旦指令被处理,它将立即停止。例如:

    RewriteRule (\w+)/?$ test.php?user=$1 [END]
    

    解决方案 B - 使正则表达式更具体

    另一个解决方案(或以及)是使正则表达式更具体,使其与test.php 不匹配。 IE。只匹配您期望的 URL 格式。

    正则表达式 (\w+)/?$ 似乎过于通用,因为它基本上只是匹配 URL 路径上的最后一组字母/数字。如果您只想匹配数字(“用户 ID”),那么您可以使正则表达式更具限制性并仅匹配数字。

    您还应该在开头锚定正则表达式,以便它匹配整个路径段,而不是仅捕获匹配的最后一部分。事实上,简单地锚定上述正则表达式也可以解决这个问题,因为test.php 将无法匹配,因为\w 不匹配点。

    例如:

    RewriteRule ^(\d+)/?$ test.php?user=$1 [L]
    

    这将只匹配最后一个路径段中的数字。


    如果我尝试

    RewriteRule ^prezzo/account/(\w+)/?$ prezzo/account/test.php?user=$1 [L]
    

    我得到 404 not found 虽然 htaccess 测试器报告该规则是 正确应用并重写 URL

    如果.htaccess 文件位于/prezzo/account 子目录中(如您所说),则上述内容将永远不会匹配,并且该指令什么也不做。

    该测试工具假定.htaccess 文件仅位于文档根目录中。如果您的 .htaccess 位于文档根目录而不是子目录中,那么该指令确实可以。

    目录上下文(例如.htaccess)中,RewriteRule 模式与目录的相对 URL路径匹配包含.htaccess 文件。


    旁白:

    在您的链接中,整个文件似乎是:

    RewriteEngine On
    #RewriteCond %{REQUEST_FILENAME} !-f
    #RewriteCond %{REQUEST_FILENAME} !-d
    #RewriteCond %{REQUEST_FILENAME} !-l
    #RewriteRule . index.php [L]
    
    RewriteRule (\w+)/?$ test.php?user=$1 [L]
    

    第一条规则被注释掉,所以这里不适用。但是,如果您取消注释第一条规则,则规则的顺序错误。因为/prezzo/account/1 的请求首先会被重写为index.php,你会遇到和以前一样的问题。

    规则的顺序很重要。

    【讨论】:

    • 谢谢MrWhite,我永远不会自己解决。我评论%{REQUEST_FILENAME} 的原因是我需要将一个长 300 字节的十六进制字符串作为参数传递(例如 account/be486ebc06e39c37...),但服务器报告“禁止”,因为它太长了(尽管浏览器可能有 URL到 2048 字节)。我读到这可能是由于%{REQUEST_FILENAME} 所以有人建议删除它,但它并没有解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    相关资源
    最近更新 更多