Apache2 重写 returns 文件扩展名

Apache2 rewrite returns filename extension

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

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= [L]

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

但是当我转到 URL 时 http://localhost/prezzo/account/1test.php 被加载 - 其中仅包含

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

它returns字符串“php”而不是“1”.

如果我尝试

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

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

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

如果我在地址栏中 copy/paste 就可以了。

But when I go to the URL http://localhost/prezzo/account/1 and test.php is loaded [...] it returns the string "php" instead of "1".

是的,发布的规则符合预期。

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

RewriteRule (\w+)/?$ test.php?user= [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 shorthand 字符 class 排除了点并且正则表达式没有锚定。)
  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= [END]

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

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

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

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

例如:

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

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


If I try with

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

I get 404 not found although htaccess tester reports that the rule is applied correctly and the URL is rewritten

如果 .htaccess 文件位于 /prezzo/account 子目录中(如您所述),则上述内容永远不会匹配,指令不执行任何操作。

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

目录上下文中(例如.htaccessRewriteRule模式匹配URL-包含 .htaccess 文件的目录的相对路径


旁白:

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

RewriteEngine On
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{REQUEST_FILENAME} !-l
#RewriteRule . index.php [L]

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

第一条规则已被注释掉,因此不适用于此处。但是,如果您取消注释第一条规则,那么规则的顺序是错误的。由于对 /prezzo/account/1 的请求将首先被重写为 index.php 并且您会遇到与以前相同的问题。

规则的顺序很重要。