简体   繁体   English

为什么 Apache mod_rewrite 删除了 uri 部分?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM