htaccess:如何从查询字符串中删除缺失值的URL参数?

3
我想要进行重定向:
  • https://www.example.com/?p2重定向到https://www.example.com/

  • https://www.example.com/?p1=v1&p2&p3=v3重定向到https://www.example.com/?p1=v1&p3=v3

  • https://www.example.com/page.php?p4=v4&p2重定向到https://www.example.com/page.php?p4=v4

您可以假设查询字符串中缺少的值始终是p2,如果这使问题更容易回答的话。

但是,在这些情况下,p2查询字符串并不总是缺少值,我也不希望在这些情况下将其删除。


1
如果参数为空,忽略该参数在应用逻辑中可能会更容易。 - arkascha
1
这是一个公正的问题:+1。请阅读Steven的回答,如果您觉得有用,请“点赞”并“接受”它。 - paulsm4
arkascha: "你需要将你的代码添加到问题中。" 参考? - oyvey
2个回答

3

.htaccess中解决问题

您可以通过多种不同的方式使用多个重写规则在.htaccess中解决此问题...

示例 1:

RewriteCond %{QUERY_STRING} ^p2$
RewriteRule . / [QSD,L]

RewriteCond %{QUERY_STRING} ^(.+)&p2$
RewriteRule . /?%1 [L]

RewriteCond %{QUERY_STRING} ^p2&(.+)$
RewriteRule . /?%1 [L]

RewriteCond %{QUERY_STRING} ^(.+)&p2(&.+)$
RewriteRule . /?%1%2 [L]

例子2:

RewriteCond %{QUERY_STRING} (^|.*&)p2(&.*|$)
RewriteRule . /?%1%2 [L]

// This doesn't give particularly clean query strings (not that they need to
// be for the server to understand it).
// e.g. 
//    ?p1=v1&p2&p3=v3 -> ?p1=v1&&p3=v3

示例 3:

RewriteCond %{QUERY_STRING} (^|.*&)p2(?:&(.*)|$)
RewriteRule . /test.php?%1%2 [L]

// ?p2&p3=v3       -> ?p3=v3
// ?p1=v1&p2       -> ?p1=v1
// ?p1=v1&p2&p3=v3 -> ?p1=v1&p3=v3

“这也利用了mod_rewrite的一个‘特性’,即在将查询字符串分配给Location HTTP响应头之前,自动截断/删除结果查询字符串中的尾部&。” @MrWhite 正如@MrWhite所指出的,一个尾随的&会被截断,因此经过更多考虑后,可以使用上述一行条件来捕获所有可能性(示例输入和输出在注释行//...中提供)。

在脚本中修复它

虽然您可以像上面展示的那样更改查询字符串,但当您可以如此轻松地在您的脚本(例如PHP)中处理它时,真的没有必要这样做。
if(empty($_GET["p2"])){
    unset($_GET["p2"]);
}

你必须进行处理页面查询字符串的操作吗?!


额外说明

上述规则会默默地删除查询字符串。如果您想让用户知道,则应根据@MrWhite的答案进行重定向,并设置标志[R=30X]和适当的HTTP响应代码:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status


2

.htaccess 中另一种方法是...

RewriteCond %{QUERY_STRING} ^&?p2(?:&|$)(.*) [OR]
RewriteCond %{QUERY_STRING} (.+)&p2(&.*|$)
RewriteRule ^ %{REQUEST_URI}?%1%2 [R=302,L]

这应该放在你的.htaccess文件顶部,位于其他重写之前。

这个处理所有没有值的p2 URL参数的查询字符串变体,并产生一个"干净"的查询字符串。URL通过外部重定向进行"修正"。(首先使用302 - 临时 - 重定向进行测试,然后再改为301 - 永久 - 如果这是意图,以避免潜在的缓存问题。)

只有两个OR'd条件中的一个会匹配。第一个条件处理p2出现在查询字符串开头的情况。第二个条件处理p2出现在查询字符串后面或末尾的情况。这样我们就不会在结果的替换中得到不匹配或双重&(URL参数分隔符)。

%1%2反向引用包含最后匹配的CondPattern(无论哪一个)的第一组和第二组捕获。基本上是p2参数之前和之后的字符串。

这也利用了mod_rewrite的一个"特性",即在被分配给Location HTTP响应头之前,结果查询字符串中的尾随&会被自动截断/删除。

然而,正如已经提到的,根据这个"错误的"p2 URL的普遍程度和出现位置来看,可能更好的方法是简单地"忽略"它,并确保你在你的HTML中设置了适当的rel="canonical"元素。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接