不能在 RewriteCond 中使用括号 QUERY_STRING
Can't use parentheses in RewriteCond QUERY_STRING
从 https://serverfault.com/questions/1013461/cant-use-parentheses-in-rewritecond-query-string 移出,因为它是这里的主题。
我需要从旧 url 捕获 UID 并将其重定向到新格式。
example.com/?uid=123
应该重定向到 example.com/user/123
什么应该起作用:
RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L]
这根本不会重定向。
但是,这样做:
RewriteCond %{QUERY_STRING} ^uid=\d+$
RewriteRule ^$ /user/%1? [L]
它转到 example.com/user
。 UID 被遗漏了,但它确实重定向了。
注意:我所做的只是删除了第二个示例中的括号。
这是为什么??如何匹配查询并捕获 UID 的值?
更新
这是一个 laravel 应用程序。我发现我确实看到的重定向可能来自应用程序,而不是 Apache。
即将推出自答...
临时添加 R=302 得到所需的结果:
RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L,R=302]
当然,这会将 302 重定向发送到 /users/123
。我想看看这是否可以通过内部重写来完成...
以下是 laravel 的默认 .htaccess 中的一些规则:
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
这会捕获不指向真实文件的路径,并将它们指向 laravel 应用程序。删除后,Apache 会为 /users/1234.
响应 404
https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_l
这样的重写可以追溯到 Apache 的 URL 解析器。然后再次处理 .htaccess(因为它仍然适用于这个新的 URL)。在这一点上,我希望上述规则能够选择不存在的路径并将其指向 laravel 应用程序...
找到了。现在写一个答案。
答案
怀特先生是对的。您必须添加 R=302
或 R=301
才能执行重定向。一个普通的 ol' 重写是行不通的。
RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L,R=302]
原因
因此,Laravel 的工作方式是:
- 你要求
/some/file
- .htaccess 告诉 apache,"hey apache, if you have a request for a file that doesn't exist just pretend it's for
index.php
"
- apache 说,"hey php, I have a request to run
index.php
and the url is /some/file
"
- php 运行脚本——哇哦——是一个巨大的 laravel 应用程序
- 随便,"hey laravel, the server said
/some/file
is the url"
- laravel 做所有这些花哨的事情,它会尝试将 url 与您的其中一条路线相匹配
现在,我添加了一条规则,将某个 URL 重写为 Laravel 应该处理的虚拟 URL。我正在匹配查询参数,但这无关紧要。 (详情见下文)
当 Apache 的重写模块遇到没有 [R] 标志的重写规则时,它会重写 URL 并将其发送回 URL 处理程序。 Apache 的 URL 处理程序然后根据所有规则处理新的 URL,包括任何适用的 .htaccess 文件中的规则。
所以所有正确的规则都得到了应用。
这里是关键启示:
最初请求的 URL 从未改变。 因此,虽然 Apache 能够使用正确的文件将请求传递给 PHP,但它也在发送旧的 URL.
因此,我们必须告诉 Apache 发送 301 或 302 重定向响应,而不是仅仅重写请求。用户将发送另一个带有 URL 的请求,Laravel 需要解析路由。
但是 with/without 括号的不同行为呢?
答案就在 Laravel 的默认 .htaccess 中。让我们看看我没有括号的旧规则:
RewriteCond %{QUERY_STRING} ^uid=\d+$
RewriteRule ^$ /user/%1? [L]
没有括号抓取uid值,%1
为空。所以我们最终将 URL 重写为 /user/
.
现在,我们要看另一组Laravel规则:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ / [L,R=301]
这规范化了 url,因此虚拟 paths/routes 不包含尾部斜杠。这样做可以使路由解析更容易。
这 returns 301 重定向到 `/users'。这与我们使用括号得到的 200 非常不同,但这并不意味着括号的行为不同。正如怀特先生在评论中所说,肯定有其他事情在做。
希望您喜欢这次旅程。我更希望这能拯救一些可怜的、迷茫的灵魂,使其免于数小时的折磨。 :)
从 https://serverfault.com/questions/1013461/cant-use-parentheses-in-rewritecond-query-string 移出,因为它是这里的主题。
我需要从旧 url 捕获 UID 并将其重定向到新格式。
example.com/?uid=123
应该重定向到 example.com/user/123
什么应该起作用:
RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L]
这根本不会重定向。
但是,这样做:
RewriteCond %{QUERY_STRING} ^uid=\d+$
RewriteRule ^$ /user/%1? [L]
它转到 example.com/user
。 UID 被遗漏了,但它确实重定向了。
注意:我所做的只是删除了第二个示例中的括号。
这是为什么??如何匹配查询并捕获 UID 的值?
更新
这是一个 laravel 应用程序。我发现我确实看到的重定向可能来自应用程序,而不是 Apache。
即将推出自答...
临时添加 R=302 得到所需的结果:
RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L,R=302]
当然,这会将 302 重定向发送到 /users/123
。我想看看这是否可以通过内部重写来完成...
以下是 laravel 的默认 .htaccess 中的一些规则:
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
这会捕获不指向真实文件的路径,并将它们指向 laravel 应用程序。删除后,Apache 会为 /users/1234.
响应 404https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_l
这样的重写可以追溯到 Apache 的 URL 解析器。然后再次处理 .htaccess(因为它仍然适用于这个新的 URL)。在这一点上,我希望上述规则能够选择不存在的路径并将其指向 laravel 应用程序...
找到了。现在写一个答案。
答案
怀特先生是对的。您必须添加 R=302
或 R=301
才能执行重定向。一个普通的 ol' 重写是行不通的。
RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L,R=302]
原因
因此,Laravel 的工作方式是:
- 你要求
/some/file
- .htaccess 告诉 apache,"hey apache, if you have a request for a file that doesn't exist just pretend it's for
index.php
" - apache 说,"hey php, I have a request to run
index.php
and the url is/some/file
" - php 运行脚本——哇哦——是一个巨大的 laravel 应用程序
- 随便,"hey laravel, the server said
/some/file
is the url" - laravel 做所有这些花哨的事情,它会尝试将 url 与您的其中一条路线相匹配
现在,我添加了一条规则,将某个 URL 重写为 Laravel 应该处理的虚拟 URL。我正在匹配查询参数,但这无关紧要。 (详情见下文)
当 Apache 的重写模块遇到没有 [R] 标志的重写规则时,它会重写 URL 并将其发送回 URL 处理程序。 Apache 的 URL 处理程序然后根据所有规则处理新的 URL,包括任何适用的 .htaccess 文件中的规则。
所以所有正确的规则都得到了应用。
这里是关键启示: 最初请求的 URL 从未改变。 因此,虽然 Apache 能够使用正确的文件将请求传递给 PHP,但它也在发送旧的 URL.
因此,我们必须告诉 Apache 发送 301 或 302 重定向响应,而不是仅仅重写请求。用户将发送另一个带有 URL 的请求,Laravel 需要解析路由。
但是 with/without 括号的不同行为呢?
答案就在 Laravel 的默认 .htaccess 中。让我们看看我没有括号的旧规则:
RewriteCond %{QUERY_STRING} ^uid=\d+$
RewriteRule ^$ /user/%1? [L]
没有括号抓取uid值,%1
为空。所以我们最终将 URL 重写为 /user/
.
现在,我们要看另一组Laravel规则:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ / [L,R=301]
这规范化了 url,因此虚拟 paths/routes 不包含尾部斜杠。这样做可以使路由解析更容易。
这 returns 301 重定向到 `/users'。这与我们使用括号得到的 200 非常不同,但这并不意味着括号的行为不同。正如怀特先生在评论中所说,肯定有其他事情在做。
希望您喜欢这次旅程。我更希望这能拯救一些可怜的、迷茫的灵魂,使其免于数小时的折磨。 :)