为什么 Apache 明确强制使用绝对 URL 重定向?

为什么 Apache 明确强制使用绝对 URL 重定向?

语境

遵循以下规则:

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

我有一个绝对重定向,例如:

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 明确强制重定向为绝对重定向?

问题

服务器位于执行 SSL 卸载的反向代理后面。因此,如果重定向保持相对,则相同的规则将适用于 HTTP/HTTPS 协议。但事实并非如此,当使用 https 请求时,会被重定向到 http。

我知道我可以将规则改为如下形式

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

但我想了解这种行为。

谢谢您的解释。

答案1

全部外部重定向R标志)会导致 mod_rewrite 需要绝对 URL。如果您没有在RewriteRule 代换那么 Apache 将使用当前协议、服务器名称和端口。Apache(或严格地说,mod_rewrite)不会在Location:HTTP 响应标头中发送相对 URL,希望用户代理能够解析该 URL。

(直到 2014 年 6 月(RFC 7231) 那相对的标头中的 URLLocation:正式成为标准的一部分。因此,特别是如果您仍在使用 Apache 2.2,那么很难说 Apache 在这里做错了什么。)

如果 Apache 返回 HTTP URL(而不是 HTTPS),那么看起来 Apache 是通过 HTTP 而不是 HTTPS 提供响应。

是的,您可以使用 mod_rewrite 手动“修复” URL。但是,REQUEST_SCHEME服务器变量可能存在相同的“问题”。如果您使用代理,则可能需要检查X-Forwarded-Proto标头(或类似内容)以确定它是“http”还是“https”。

除了在指令本身中(有条件地)强制使用 HTTPS 之外,您还可以力量在服务器配置中使用ServerName(和UseCanonicalName) 指令启用 HTTPS。但是,我认为这并不可取,您需要灵活应对?

你也可以编辑Location:头,然后再将其发送回客户端。使用 mod_headers,您可以通过手动删除方案 + 主机名来强制使用相对 URL,如这个 StackOverflow 答案

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

进一步参考:

相关内容