为什么 Apache mod_rewrite 删除 uri 部分?
Why does Apache mod_rewrite remove the uri part?
我正在尝试将 Apache 配置为我们的 websoket 服务器 http://localhost:8000
(在同一个 OS 上)的加密代理 https://chat.example.com
。我根据官方文档启用了 mod_proxy、mod_proxy_http、mod_proxy_wstunnel、mod_rewrite 和 mod_ssl。
然后我向 https://chat.example.com/connection/info?t=123144343
发出常规 https GET 请求,但 Apache 将其重写为 http://localhost:8000/?t=123144343
而不是 http://localhost:8000/connection/info?t=123144343
。为什么?
<VirtualHost *:443>
ServerAdmin admin@example.com
ServerName chat.example.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^(.*)$ ws://localhost:8000/ [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^(.*)$ http://localhost:8000/ [P,L]
ProxyRequests Off
ProxyPreserveHost On
SSLEngine on
SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2 +TLSv1.3
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/example.com-chain.crt
LogLevel rewrite:trace7
ErrorLog /var/log/example.com/chat_error.log
CustomLog /var/log/example.com/chat_access.log io
</VirtualHost>
[Wed Dec 25 18:57:16.057448 2019] [rewrite:trace2] [pid 9604:tid 140105269184256] mod_rewrite.c(483): init rewrite engine with requested uri /connection/info, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057523 2019] [rewrite:trace3] [pid 9604:tid 140105269184256] mod_rewrite.c(483): applying pattern '^(.*)$' to uri '/connection/info', referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057566 2019] [rewrite:trace4] [pid 9604:tid 140105269184256] mod_rewrite.c(483): RewriteCond: input='' pattern='=websocket' [NC] => not-matched, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057600 2019] [rewrite:trace3] [pid 9604:tid 140105269184256] mod_rewrite.c(483): applying pattern '^(.*)$' to uri '/connection/info', referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057637 2019] [rewrite:trace4] [pid 9604:tid 140105269184256] mod_rewrite.c(483): RewriteCond: input='' pattern='!=websocket' [NC] => matched, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057670 2019] [rewrite:trace2] [pid 9604:tid 140105269184256] mod_rewrite.c(483): rewrite '/connection/info' -> 'http://localhost:8000/', referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057702 2019] [rewrite:trace2] [pid 9604:tid 140105269184256] mod_rewrite.c(483): forcing proxy-throughput with http://localhost:8000/, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057735 2019] [rewrite:trace1] [pid 9604:tid 140105269184256] mod_rewrite.c(483): go-ahead with proxy request proxy:http://localhost:8000/ [OK], referer: https://example.com/personal/chats
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^(.*)$ ws://localhost:8000/ [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^(.*)$ http://localhost:8000/ [P,L]
您正在使用 RewriteRule
模式 捕获 URL 路径,即。 (.*)
。但是,您没有在 替换 中使用这个捕获的 URL 路径,而是简单地重写到文档根目录:http://localhost:8000/
。查询字符串被隐式复制到 替换 。
您需要使用 </code> 反向引用将捕获的 URL 路径包含在 <em> 替换 </em> 中。例如:</p>
<pre><code>RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^(.*)$ ws://localhost:8000 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^(.*)$ http://localhost:8000 [P,L]
请注意,在 virtualhost 上下文中,与 RewriteRule
模式 匹配的 URL 路径是root-relative 并包含斜杠前缀,因此斜杠不应包含在 susbtitution 中(除非从捕获的模式中省略)。
如果这不起作用,请尝试使用 REQUEST_URI
服务器变量:
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^ ws://localhost:8000%{REQUEST_URI} [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^ http://localhost:8000%{REQUEST_URI} [P,L]
编辑: 尽管我从问题历史记录中看到(令我感到惊讶的是我最初没有看到这一点),但令人困惑的是,您原始问题中的代码块已经包括
反向引用,它只是在您最近 编辑 之后才被删除?! (虽然,根据它的实现方式,它会在 URl-路径的开头导致双斜杠。)
我正在尝试将 Apache 配置为我们的 websoket 服务器 http://localhost:8000
(在同一个 OS 上)的加密代理 https://chat.example.com
。我根据官方文档启用了 mod_proxy、mod_proxy_http、mod_proxy_wstunnel、mod_rewrite 和 mod_ssl。
然后我向 https://chat.example.com/connection/info?t=123144343
发出常规 https GET 请求,但 Apache 将其重写为 http://localhost:8000/?t=123144343
而不是 http://localhost:8000/connection/info?t=123144343
。为什么?
<VirtualHost *:443>
ServerAdmin admin@example.com
ServerName chat.example.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^(.*)$ ws://localhost:8000/ [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^(.*)$ http://localhost:8000/ [P,L]
ProxyRequests Off
ProxyPreserveHost On
SSLEngine on
SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2 +TLSv1.3
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/example.com-chain.crt
LogLevel rewrite:trace7
ErrorLog /var/log/example.com/chat_error.log
CustomLog /var/log/example.com/chat_access.log io
</VirtualHost>
[Wed Dec 25 18:57:16.057448 2019] [rewrite:trace2] [pid 9604:tid 140105269184256] mod_rewrite.c(483): init rewrite engine with requested uri /connection/info, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057523 2019] [rewrite:trace3] [pid 9604:tid 140105269184256] mod_rewrite.c(483): applying pattern '^(.*)$' to uri '/connection/info', referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057566 2019] [rewrite:trace4] [pid 9604:tid 140105269184256] mod_rewrite.c(483): RewriteCond: input='' pattern='=websocket' [NC] => not-matched, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057600 2019] [rewrite:trace3] [pid 9604:tid 140105269184256] mod_rewrite.c(483): applying pattern '^(.*)$' to uri '/connection/info', referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057637 2019] [rewrite:trace4] [pid 9604:tid 140105269184256] mod_rewrite.c(483): RewriteCond: input='' pattern='!=websocket' [NC] => matched, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057670 2019] [rewrite:trace2] [pid 9604:tid 140105269184256] mod_rewrite.c(483): rewrite '/connection/info' -> 'http://localhost:8000/', referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057702 2019] [rewrite:trace2] [pid 9604:tid 140105269184256] mod_rewrite.c(483): forcing proxy-throughput with http://localhost:8000/, referer: https://example.com/personal/chats
[Wed Dec 25 18:57:16.057735 2019] [rewrite:trace1] [pid 9604:tid 140105269184256] mod_rewrite.c(483): go-ahead with proxy request proxy:http://localhost:8000/ [OK], referer: https://example.com/personal/chats
RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteRule ^(.*)$ ws://localhost:8000/ [P,L] RewriteCond %{HTTP:Upgrade} !=websocket [NC] RewriteRule ^(.*)$ http://localhost:8000/ [P,L]
您正在使用 RewriteRule
模式 捕获 URL 路径,即。 (.*)
。但是,您没有在 替换 中使用这个捕获的 URL 路径,而是简单地重写到文档根目录:http://localhost:8000/
。查询字符串被隐式复制到 替换 。
您需要使用 </code> 反向引用将捕获的 URL 路径包含在 <em> 替换 </em> 中。例如:</p>
<pre><code>RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^(.*)$ ws://localhost:8000 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^(.*)$ http://localhost:8000 [P,L]
请注意,在 virtualhost 上下文中,与 RewriteRule
模式 匹配的 URL 路径是root-relative 并包含斜杠前缀,因此斜杠不应包含在 susbtitution 中(除非从捕获的模式中省略)。
如果这不起作用,请尝试使用 REQUEST_URI
服务器变量:
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^ ws://localhost:8000%{REQUEST_URI} [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^ http://localhost:8000%{REQUEST_URI} [P,L]
编辑: 尽管我从问题历史记录中看到(令我感到惊讶的是我最初没有看到这一点),但令人困惑的是,您原始问题中的代码块已经包括 反向引用,它只是在您最近 编辑 之后才被删除?! (虽然,根据它的实现方式,它会在 URl-路径的开头导致双斜杠。)