mod_rewrite规则在.htaccess中不起作用以更改URL
我正在尝试重写下面的URL,但是URL只是不会更改,没有错误。
当前URL:
https://example.com/test/news/?c=value1&s=value2&id=9876
预期的URL:
https://example.com/test/news/value1/value2
我的.htaccess
RewriteEngine On
RewriteRule ^test/news/([^/]*)/([^/]*)$ /test/news/?c=$1&s=$2&id=1 [L]
I'm trying to rewrite the below URL but the URLs just don't change, no errors.
Current URL:
https://example.com/test/news/?c=value1&s=value2&id=9876
Expected URL:
https://example.com/test/news/value1/value2
My .htaccess
RewriteEngine On
RewriteRule ^test/news/([^/]*)/([^/]*)$ /test/news/?c=$1&s=$2&id=1 [L]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
但这里的重要一点(我认为您丢失了)是在您的所有内部链接中必须在您的应用程序中内部更改URL。常见的误解是,
.htaccess
仅可用于更改URL的格式。尽管.htaccess
是其中的重要组成部分,但它只是 part 。是的,您可以在
.htaccess
中实现重定向,以从旧URL重定向到新URL-这对于保留SEO至关重要(请参见下文),但这对于您的应用程序工作并不重要。如果您不首先更改内部链接中的URL,则:“旧” URL仍在HTML源中暴露。当用户徘徊或复制链接时,他们会看到并复制“旧” URL。
用户每次单击您的内部链接之一时,它们会在外部重定向到“新” URL。这对您的用户来说很慢,对SEO不利(您绝对不应链接到已重定向的URL),并且对您的服务器不利,因为它可能会使您击中服务器的请求数量增加一倍(好的,301个在本地缓存)。
从@imsop的答案 此参考问题有关该主题:
因此,一旦您将内部链接更改为“新”(预期)格式,例如。
/test/news/value1/value2
(或应该是/test/test/news/news/value1/value2/id
e/test/test/news/news/news/id/ideal1 /value2
请参阅下面的这内在内部将请求从
/test/news/< value1>/< value2>
to/test/test/news/?c =< value1> ;& id = 1
。但是,有两个问题:/test/news/
本身不是有效的端点。这需要进一步的重写。也许您正在提供DirectoryIndex文档(例如index.php
)?这可能对您而言是无缝的,但这需要附加的内部子重试,并使规则取决于配置的其他元素。您应该直接重写处理请求的文件。例如。/test/news/index.php?c=&s =< value2>; gt;& id = 1
(请记住,这完全隐藏在用户中)。您正在硬编码
id = 1
参数?每个URL都应该具有相同的id
吗?还是应该在“新” URL(我期望这是什么)中通过的?id
表示什么?如果这对于URL的路由至关重要,则id
应在URL路径中出现,以防copy/pasted/sharde时url意外截断。如果需要
ID
,则需要在“新” URL中传递它。我们只有“新” URL来路由请求,因此信息不能隐藏。因此,如果“新” URL现在为
/test/news/< id>/< value1>/&lt value2>
,那么重写将需要像这样:然后(可选) *1 )您可以实现外部重定向以保留SEO。这是针对已索引无法更新的“旧” URL或第三方入站链接的搜索引擎 - 需要纠正这些链接以告知搜索引擎,并使用户在“新”规范URL上遵循了Out of Out of Out。 - 日期入站链接。
( *1 如果您要更改现有URL,则不是“可选”,而是关于您的应用程序功能的可选。)
此“重定向”在之前 上述重写:
$ 0
BackReference包含Rewriterule
staters 的完整匹配,即。test/news/
在这种情况下 - 这只是保存重复。%1
,%2
和%3
backReferences包含从前面条件捕获的值。 IE。c
,s
和id
url参数的值分别。请注意,URL参数/路径段不应像您的原始指令(即
([^/]*)
)那样可选。如果它们是可选的并且被省略,则会产生的URL变得模棱两可。例如。< value2>
省略< value1>
如果< value1>
被省略。请注意,URL参数必须按照说明的顺序为顺序。如果您以不同的顺序(甚至与其他参数混合)的“旧” URL不匹配“旧” URL,则可以用其他复杂性来解释这一点。 (在您的服务器端脚本中执行此重定向可能更容易,而不是
.htaccess
。)第一个针对
redirect_status
环境变量检查的条件重定向直接请求,而不是以后的重写(否则会导致重定向循环)进行重写。 Apache 2.4上的一种替代方法是使用end
flag重写
而不是。QSD
flag(apache 2.4)从请求中丢弃原始查询字符串。您应该首先使用302(临时)重定向测试,以避免潜在的缓存问题,并且仅一旦测试了一切都可以按预期工作,则只能更改为301(永久)重定向。浏览器将301持续缓存,因此可以使测试有问题。
摘要
您的完整
.htaccess
文件应该看起来像这样:But the important point here (that I think you are missing) is that the URL must already have been changed internally in your application - in all your internal links. It is a common misconception that
.htaccess
alone can be used to change the format of the URL. Whilst.htaccess
is an important part of this, it is only part of it.Yes, you can implement a redirect in
.htaccess
to redirect from the old to new URL - and this is essential to preserve SEO (see below), but it is not critical to your application working. If you don't first change the URL in your internal links then:The "old" URL is still exposed in the HTML source. When a user hovers over or copies the link, they are seeing and copying the "old" URL.
Every time a user clicks one of your internal links they are externally redirected to the "new" URL. This is slow for your users, bad for SEO (you should never link to a URL that is redirected) and bad for your server, as it potentially doubles the number of requests hitting your server (OK, 301s are cached locally).
To quote from @IMSoP's answer to this reference question on the subject:
So, once you have changed your internal links to the "new" (expected) format, eg.
/test/news/value1/value2
(or should that be/test/news/value1/value2/id
or even/test/news/id/value1/value2
? See below), then you can do as follows...This internally rewrites a request from
/test/news/<value1>/<value2>
to/test/news/?c=<value1>&s=<value2>&id=1
. However, there are a couple of issues with this:/test/news/
is not itself a valid endpoint. This requires further rewriting. Perhaps you are serving a DirectoryIndex document (eg.index.php
)? This might appear seamless to you, but this requires an additional internal subrequest and makes the rule dependent on other elements of the config. You should rewrite directly to the file that handles the request. eg./test/news/index.php?c=<value1>&s=<value2>&id=1
(remember, this is entirely hidden from the user).You are hardcoding the
id=1
parameter? Should every URL have the sameid
? Or should this be passed in the "new" URL (which is what I would expect)? What does theid
represent? If this is critical to the routing of the URL then theid
should appear earlier in the URL-path, in case the URL gets accidentally truncated when copy/pasted/shared.If the
id
is required then it needs to be passed in the "new" URL. We only have the "new" URL to route the request, so the information can't be hidden.So, if the "new" URL is now
/test/news/<id>/<value1>/<value2>
then the rewrite would need to be like this instead:Then (optionally*1) you can implement an external redirect in order to preserve SEO. This is for search engines that have indexed the "old" URLs or third party inbound links that cannot be updated - these need to be corrected to inform search engines of the change and get the user on the "new" canonical URL having followed an out-of-date inbound link.
(*1 It's not "optional" if you are changing an existing URL, but optional with regards to your application being functional.)
This "redirect" goes before the above rewrite:
The
$0
backreference contains the full match from theRewriteRule
pattern, ie.test/news/
in this case - this simply saves repetition.The
%1
,%2
and%3
backreferences contain the values captured from the preceding condition. ie. the values of thec
,s
andid
URL parameters respectively.Note that the URL parameters / path segments should not be optional as in your original directive (ie.
([^/]*)
). If they are optional and they are omitted, then the resulting URL becomes ambiguous. eg.<value2>
becomes<value1>
if<value1>
is omitted.Note that the URL parameters must be in the order as stated. If you have a mismatch of "old" URLs with these params in a different order (or even intermixed with other params) then this can be accounted for with additional complexity. (It may be easier to perform this redirect in your server-side script, instead of
.htaccess
.)The first condition that checks against the
REDIRECT_STATUS
environment variable ensures that we only redirect direct requests and not rewritten requests by the later rewrite (which would otherwise result in a redirect loop). An alternative on Apache 2.4 is to use theEND
flag on theRewriteRule
instead.The
QSD
flag (Apache 2.4) discards the original query string from the request.You should test first with a 302 (temporary) redirect to avoid potential caching issues and only change to a 301 (permanent) redirect once you have tested that everything works as intended. 301s are cached persistently by the browser so can make testing problematic.
Summary
Your complete
.htaccess
file should look something like this: