为什么Apache显式强制使用绝对urlredirect?

上下文

遵循以下规则:

# Redirect root url to /tvs RewriteRule ^/$ /tvs [R=301,L] 

我有一个绝对的redirect,如:

 HTTP/1.1 301 Moved Permanently Server: nginx Date: Fri, 24 Mar 2017 16:42:23 GMT Content-Type: text/html; charset=iso-8859-1 Content-Length: 312 Location: http://www.tvsvizzera.it/tvs Vary: Accept-Encoding X-Node: pcache02 X-Cached: MISS Proxy-Connection: Keep-Alive Connection: Keep-Alive 

并在rewrite.log中我有以下几点

 10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (2) init rewrite engine with requested uri / 10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (2) rewrite '/' -> '/tvs' 10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (2) explicitly forcing redirect with http://www.tvsvizzera.it/ tvs 10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (1) escaping http://www.tvsvizzera.it/tvs for redirect 10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (1) redirect to http://www.tvsvizzera.it/tvs [REDIRECT/301] 

为什么apache明确强制redirect是绝对的?

问题

服务器位于执行SSL卸载的逆向代理之后。 所以如果redirect保持相对的话,同样的规则对于协议HTTP / HTTPS都是有效的。 但情况并非如此,当用https请求时,会被redirect到http。

我知道我可以改变规则是这样的

 RewriteRule ^/$ %{ENV:REQUEST_SCHEME}://%{HTTP_HOST}/tvs [R=permanent,L] 

但我想了解这种行为。

感谢您的任何解释。

所有外部redirectR标志)都会导致mod_rewrite需要绝对URL。 当你没有在RewriteRule replace中明确包含scheme和hostname时,Apache将使用当前协议,服务器名称和端口。 Apache(或严格来说,mod_rewrite)不会在Location: HTTP响应头中发回相对URL,希望用户代理能够parsingURL。

(直到2014年6月( RFC 7231 ), Location: header中的相对 URL正式成为标准的一部分,所以,特别是如果你还在Apache 2.2上,那么很难说Apache在这里做错了什么。)

如果Apache正在发回一个HTTP URL(而不是HTTPS),那么Apache似乎是通过HTTP提供回应,而不是HTTPS。

是的,您可以使用mod_rewrite手动“修复”URL。 但是, REQUEST_SCHEME服务器variables可能具有相同的“问题”。 如果你在一个代理的后面,那么你可能需要检查X-Forwarded-Proto头(或类似的)是否是“http”或“https”。

除了(有条件地)在指令中强制HTTPS本身,您也可以使用ServerName (和UseCanonicalName )指令在服务器configuration中强制使用 HTTPS。 但是,我认为这是不可取的,你需要灵活?

在发送回客户端之前,您还可以编辑 Location:标题。 使用mod_headers,你可以通过手动去掉scheme + hostname来强制一个相对的URL,就像在这个StackOverflow答案中所build议的那样:

 Header edit Location "^https?://[a-zA-Z0-9.-]+" "" 

进一步参考: