【问题标题】:htaccess RewriteRule with literal question marks (not query string)htaccess RewriteRule 带有文字问号(不是查询字符串)
【发布时间】:2018-09-05 14:58:04
【问题描述】:

我需要能够匹配问号,因为存在翻译文本编码错误,并且部分 URL 最终被硬编码为带有问号。这是我需要重写的 URL 示例:

https://example.com/Documentation/Product????/index.html

这是我当前的重写规则。当“产品”后面的字符不是问号时,它可以工作,但如果是,则规则不适用。

RewriteRule "^Documentation/Product[^/]+/(.*)$" "https://s3.amazonaws.com/company-documentation/Help/Product/$1" [L,NC]

如何确保在此规则中问号也被视为字符?我不能期望 URL 中只有问号而不是原始的非英文字符,所以我希望上面的规则同时匹配问号和任何其他字符。

我发现这个话题似乎很相关,但标志没有帮助,答案也没有解释如何克服“旁白”中提到的问题。 https://webmasters.stackexchange.com/questions/107259/url-path-with-encoded-question-mark-results-in-incorrect-redirect-when-copied-to

【问题讨论】:

  • 这应该与您现有的规则一起使用吗? IE。您有 /Documentation/Product<something>/<optional-end-part> 形式的 URL 重定向到 https://s3.amazonaws.com/company-documentation/Help/Product/<optional-end-part>index.html 是变量吗?即使在这些格式错误的 URL 中?
  • index.html 部分是可变的。我对“普通”网址还有其他规则。这个只需要抓住奇怪的作为产品的最后手段。
  • Aside:虽然它可能看起来相关,但链接的问题与此问题没有直接关系。在链接的问题中,源 URL 在 URL 路径中有 literal 问号(即问号是 URL 编码的),因此没有查询字符串(问题 #1)。这也被捕获(问题#2)并传递给替换(问题#3)。链接问题中的“旁白”并不是真正描述“问题”,只是一个过程。您可以使用 NE 标志来防止后续的 ? 被 URL 编码,但这不一定是可取的。

标签: .htaccess mod-rewrite url-rewriting


【解决方案1】:
https://example.com/Documentation/Product????/index.html

你说它“不是查询字符串”,但实际上它就是这样。这就是为什么你不能将它与RewriteRule pattern 匹配。以上网址拆分如下:

  • URL-path:/Documentation/Product(由RewriteRule匹配模式
  • 查询字符串:???/index.html(注 3 ? - 第一个开始查询字符串)

要匹配查询字符串,您需要一个额外的 RewriteCond 指令来检查 QUERY_STRING 服务器变量。

例如,要匹配上述 URL,您需要执行以下操作:

RewriteCond %{QUERY_STRING} ^\?*/index\.html
RewriteRule ^Documentation/Product$ https://s3.amazonaws.com/company-documentation/Help/Product/index.html [NC,R,L]

这匹配查询字符串开头的任意数量的错误?

我添加了R (redirect) 标志。您的指令(没有 R 标志)无论如何都会触发外部重定向(因为您在 substitution 中指定了绝对 URL),但在这里明确表示要好得多。这也是一个临时的 (302) 重定向。如果这应该是永久性的 (301),则将其更改为 R=301,但前提是您确认它工作正常(301 被浏览器硬缓存,因此可能会导致测试出现问题)。


更新:

...所以我希望上面的规则同时匹配问号和任何其他字符。

只有在 URL 中有问号时才会有查询字符串,所以我认为最好将这两条规则分开。

如果查询字符串的开头可能有任何错误字符,并且您想捕获 URL 的结尾部分(就像您在原始指令中所做的那样,例如index.html),那么您可以修改以上阅读:

RewriteCond %{QUERY_STRING} /(.*)$
RewriteRule ^Documentation/Product$ https://s3.amazonaws.com/company-documentation/Help/Product/%1 [NC,R,L]

注意 substitution 字符串中的 %1(相对于 $1)反向引用。这是对上次匹配的 CondPattern 中捕获组的反向引用(即/(.*)$)。

对于不包含?(即查询字符串)的更多“正常”网址,您可以使用现有指令(但请记住包含R 标志)遵循此指令。

注意:在这个例子中,用双引号括起来的参数是完全可选的。只有在 patternsubstitution 参数中有非转义空格时,它们才是必需

总结

# Redirect URLs of the form:
# "/Documentation/Product?<anything#1>/<anything#2>"
RewriteCond %{QUERY_STRING} /(.*)$
RewriteRule ^Documentation/Product$ https://s3.amazonaws.com/company-documentation/Help/Product/%1 [NC,R,L]

# Redirect URL-paths of the form (no query string):
# "/Documentation/Product<something>/<anything>"
RewriteRule ^Documentation/Product[^/]+/(.*) https://s3.amazonaws.com/company-documentation/Help/Product/$1 [NC,R,L]

【讨论】:

  • 这似乎与我读到的关于 URL 中第一个问号的内容一致。我一会儿试试这个。谢谢!
  • 我已经用更“通用”的解决方案更新了我的答案(关于您的 cmets 和更新的问题)。
猜你喜欢
  • 2013-12-21
  • 2015-05-27
  • 2019-01-02
  • 2018-07-25
  • 2014-08-01
  • 2013-03-26
  • 2013-06-14
  • 1970-01-01
  • 2020-03-18
相关资源
最近更新 更多