[英]Why does Apache mod_rewrite remove the uri part?
I'm trying to configure Apache as an encryption proxy https://chat.example.com
for our websoket server http://localhost:8000
(on the same OS).我正在尝试将 Apache 配置为我们的 websoket 服务器
http://localhost:8000
(在同一操作系统上)的加密代理https://chat.example.com
。 I enabled mod_proxy, mod_proxy_http, mod_proxy_wstunnel, mod_rewrite and mod_ssl according to the official docs.我根据官方文档启用了 mod_proxy、mod_proxy_http、mod_proxy_wstunnel、mod_rewrite 和 mod_ssl。 Then I made a regular https GET request to the
https://chat.example.com/connection/info?t=123144343
, but Apache rewrote it to http://localhost:8000/?t=123144343
instead of http://localhost:8000/connection/info?t=123144343
.然后我向
https://chat.example.com/connection/info?t=123144343
发出了一个常规的 https GET 请求,但 Apache 将其重写为http://localhost:8000/?t=123144343
而不是http://localhost:8000/connection/info?t=123144343
。 Why?为什么?
<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]
You are capturing the URL-path with the RewriteRule
pattern , ie.您正在使用
RewriteRule
模式捕获 URL 路径,即。 (.*)
. (.*)
。 However, you are not making use of this captured URL-path in the substitution and simply rewriting to the document root: http://localhost:8000/
.但是,您没有在替换中使用此捕获的 URL 路径,而只是重写到文档根目录:
http://localhost:8000/
。 The query string is copied through to the substitution implicitly.查询字符串被隐式复制到替换中。
You need to include the captured URL-path in the substitution using the $1
backreference.您需要使用
$1
反向引用在替换中包含捕获的 URL 路径。 For example:例如:
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^(.*)$ ws://localhost:8000$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^(.*)$ http://localhost:8000$1 [P,L]
Note that in a virtualhost context, the URL-path matched by the RewriteRule
pattern is root-relative and includes the slash prefix, so the slash should not be included in the susbtitution (unless omitted from the captured pattern).请注意,在虚拟主机上下文中,由
RewriteRule
模式匹配的 URL 路径是相对于根的,并且包含斜杠前缀,因此斜杠不应包含在susbtitution 中(除非从捕获的模式中省略)。
If this fails to work, then try using the REQUEST_URI
server variable instead:如果这不起作用,请尝试改用
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]
EDIT: Although, rather confusingly, I see from the question history (as I was surprised I didn't see this initially) that the code block in your original question already included the $1
backreference and it was only removed after your recent edit ?!编辑:虽然相当令人困惑,但我从问题历史中看到(因为我很惊讶我最初没有看到这一点),您原始问题中的代码块已经包含
$1
反向引用,并且它仅在您最近编辑后才被删除?! (Although, with how it was implemented, it would have resulted in a double slash at the start of the URl-path.) (虽然,根据它的实现方式,它会在 URl 路径的开头产生双斜线。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.