apache RewriteRule 匹配 % 编码 URL 的语法?(修复字符编码问题;windows-1252 <=> utf-8 )

Jul*_*ers 5 mod-rewrite utf-8 encoding apache-2.4

我托管的网页的 URL 中包含“ \”,与托管静态文件的project\xc2\xb2磁盘目录相匹配。project\xc2\xb2

\n

此页面由基于 java 的客户端用来从 URL(生物信息学软件IGV)加载数据。\n我的页面以 的形式列出 URL http://localhost:60151/load?file=http://example.org/project\xc2\xb2/some/data/file.bam。\n在浏览器中单击这些链接将导致 IGV 客户端(在本地主机上运行)发出请求GET http://example.org/project\xc2\xb2/some/data/file.bam从我的服务器。

\n

Linux/Mac 上的 \xe2\x9c\x85 IGV 通过请求此 URL 作为 UTF-8 编码\xc2\xb2=进行响应%C2%B2,一切正常。
\n\xe2\x9d\x8c 我新获得的Win-10用户的客户端请求\xc2\xb2= %B2(windows-1252编码),导致404-not-found。

\n

在尝试了几十种方法之后,我不知道如何帮助这个用户。

\n

我的印象是我应该能够在服务器端动态重写错误编码的 URL,以便它们最终仍然提供所需的数据,但是我不知道使规则模式匹配的神奇字符组合转义字符。

\n
\n

我已经尝试过的事情

\n
    \n
  • 仔细检查 404 是否不是网络问题;我看到GET %B2我的ssl_access_logwith404作为返回的状态码,所以它确实是服务器在做。
  • \n
  • “正确的”方式:在将 URL 提供给客户端之前对 URL 进行 UrlEncoding。Perl 的将 变成URI::Encode encode_uri(显然?),这在某种程度上更加错误\xc2\xb2%C3%82%C2%B2\xc3\x83\xc2\xb2
  • \n
  • 三次检查提供加载 URL 的网页是否以 utf-8 形式提供\n
      \n
    • 它提供标头Content-Type: text/html; charset=UTF-8
    • \n
    • 设置AddDefaultCharset UTF-8httpd.conf
    • \n
    • 看来编码信息没有从网络浏览器API-链接-单击传输到Java程序
    • \n
    \n
  • \n
  • 通过符号链接“加倍”目录project\xc2\xaa -> project\xc2\xb2project%B2 -> project\xc2\xb2 \xc2\xaa是 的 UTF8 匹配%B2 编辑:\xc2\xaa 没有任何关系;不知道我从哪里得到的
  • \n
  • 尝试mod_rewrite用几种不同的方式将“坏”网址变成好的网址,但似乎都没有成功:
  • \n
\n
RewriteEngine on\n# RewriteRule Pattern Substitution [flags]\nRewriteRule (.*)project%B2/(.*) $1project\xc2\xb2/$2 [NE] # encoded \'bad\' request, unencoded redirect\nRewriteRule (.*)\xc2\xb2(.*) $1%C2%B2$2 [B,NE]            # config file is utf-8 encoded, so this is senseless.      \nRewriteRule (.*)%B2(.*) $12$2 [B,NE]               # doesn\'t match?        \nRewriteRule (.*)TZZT(.*) $1test$2                  # works, so RewriteEngine is working\n
Run Code Online (Sandbox Code Playgroud)\n

RewriteRule和RewriteRuleFlags文档也无法帮助我理解应该如何编码- 部分以便它能够工作:-(Pattern

\n
\n

类似的问题在这里

\n\n

Jul*_*ers 2

解决方案

\n

RewriteRule必须使用\\x而不是%为了匹配%编码的URL!(字节序列的 PCRE 语法)

\n

mod_rewrite-config 使用 PCRE 正则表达式语法,并对解码后的 URL 进行操作,因此%RewriteRule模式中键入 -encoding 会导致它查找文字 -%字符,而不是编码值。
\nRewriteRules 中正确的转义字符是,因此可以使用\\xURL 编码值进行匹配(或者,它不区分大小写)。%B2\\xb2\\xB2

\n

请注意,这RewriteRule是针对字符编码问题的一个 hacky 解决方案,仅当恰好有一个特定的错误编码字符位于特定的可预测位置时才有效。

\n

有关任意位置多个错误编码字符的通用解决方案,请参阅Apache .htaccess 能否将编码 URI 中的百分比编码从 Win-1252 转换为 UTF-8?,它提出了一种使用RewriteMap全功能编程语言耦合到外部程序的通用解决方案。

\n

正确解决方案仍然是从源头上防止这种情况发生,在整个链中使用显式的%编码。这可以避免依赖于操作系统的编码意外发生在您无法控制的“中间某处”。\n(假设路径上没有客户端进行双重编码,这应该是一种应受惩罚的罪行..)

\n
\n

我是怎么来到这里的

\n

绝望之余,我按照mod_rewrite 文档LogLevel Warn rewrite:trace3中的建议提高了服务器范围的日志记录。警告这会(严重)影响服务器性能,但这是可以管理的,因为这是一个低流量服务器,并且没有预先存在的重写。

\n

额外的日志记录被发送到 ( ssl_)中error_log。\n这让我深入了解了匹配的具体尝试方式,以及规则和 URI 的内部表示形式mod_rewrite

\n

摘录自ssl_error_log(为简洁起见,省略了许多列),\n带有规则RewriteRule (.*)project%B2/(.*) $1project\xc2\xb2/$2 [NE,L]

\n
[rewrite:trace3] applying pattern \'(.*)project%B2/(.*)\' to uri \'project\\xb2/\'\n[rewrite:trace1] pass through /var/www/html/example.org/project\\xb2\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,来自客户端的 request-uri 是这样写的\\xb2,但我的模式使用%B2.

\n

将规则语法与 uri 语法进行匹配,并使用规则RewriteRule (.*)project\\xB2/(.*) $1project\xc2\xb2/$2 [NE,L]

\n
[rewrite:trace3] applying pattern \'(.*)project\\\\xb2/(.*)\' to uri \'project\\xb2/\'\n[rewrite:trace2] rewrite \'project\\xb2/\' -> \'project%c2%b2/\'\n[rewrite:trace1] internal redirect with /auth-test/project\\xc2\\xb2/ [INTERNAL REDIRECT]\n
Run Code Online (Sandbox Code Playgroud)\n

成功!正如我们所看到的,我们现在正在匹配!

\n
\n

为什么没有[R]/[R=302]标志?

\n

由于这是一个字符编码问题,我认为进行额外的 HTTP 往返不会增加价值;除非我在将其输入客户端 java 程序之前修复编码问题,否则输入客户端的每个链接都会再次遇到相同的问题。

\n
\n

别忘了RewriteBase

\n

请注意,这个缩短的版本省略了设置正确的RewriteBase,这可能会搞乱重写的路径,具体取决于您的conf路径写入位置(例如<Directory>vs <Location>)。没有RewriteBase我不小心重定向到 \xe2\x9d\x8chttps://example.org/var/www/html/rewrite-testing/project\xc2\xb2 而不是 \xe2\x9c\x85https://example.org/rewrite-testing/project\xc2\xb2

\n