我想做以下重定向:
- 如果没有语言数据,请前往英文网站
- 当用户的浏览器语言为匈牙利语时,转到匈牙利网站
- 当用户的浏览器语言不是匈牙利语时,转到英文网站
我在我的 Apache conf 中使用以下命令:
RewriteCond %{REQUEST_URI} !^[^.]*/$
RewriteCond %{HTTP:Accept-Language} (hu) [NC]
RewriteRule ^(.*)$ https://example.net/hu [L]
RewriteCond %{HTTP:Accept-Language} (!hu) [NC]
RewriteRule ^(.*)$ https://example.net/en [L]
问题是当我仅请求时https://example.net
,没有重定向,只列出根文件夹中的文件。
编辑:当前的重写规则:
<IfModule mod_rewrite.c>
RewriteEngine On
# This will enable the Rewrite capabilities
RewriteCond %{HTTP:Accept-Language} hu [NC]
RewriteRule !^/?hu https://example.net/hu [L]
RewriteCond %{HTTP:Accept-Language} !hu [NC]
RewriteRule !^/?en https://example.net/en [L]
</IfModule>
答案1
RewriteCond %{REQUEST_URI} !^[^.]*/$
这状况将阻止对文档根目录的请求被“重定向”。(不太清楚此指令背后的想法是什么?)
您还应该修改RewriteRule
模式分别排除/hu
和/en
目录,以避免不必要的(额外)循环。例如:
RewriteCond %{HTTP:Accept-Language} hu [NC]
RewriteRule !^/?hu https://example.net/hu/ [R,L]
RewriteCond %{HTTP:Accept-Language} !hu [NC]
RewriteRule !^/?en https://example.net/en/ [R,L]
请注意,由于/hu
和/en
是物理目录,因此您应该在目标 URL 上添加尾部斜杠。否则,mod_dir 将发出第二个 301 重定向以附加尾部斜杠。
但是,这种逻辑是有缺陷的。Accept-Language
标题可以包含多种语言。每种语言都可以“加权”,表明用户的偏好。按照你的逻辑,匈牙利语网站会显示给接受匈牙利语但更喜欢英语的用户。一个简化的解决方案是认为首选语言是第一个提到的语言,在这种情况下,更改条件模式分别为^hu
和!^hu
。然而,这并不一定在所有情况下都是可靠的。
并且...对于 SEO(和用户)来说,你可能根本不应该重定向,而只是让用户自己决定——也许推荐基于感知的语言偏好的语言版本。除了“不可靠”(如上所述)之外,如果您强制重定向,那么搜索引擎可能只会看到一个版本。对于搜索引擎,您应该确保您拥有适当的<link HREFLANG>
元素。另请参阅 Google 帮助文档:管理多区域和多语言站点
列出了根文件夹中的文件。
在旁边:如果文件上市那么听起来您需要禁用目录索引。Indexes
从主Options
指令中删除该选项,或在虚拟主机中禁用该选项:
Options -Indexes
更新#1:从您的问题中不明显看出的问题是,您从 HTTP 获得的响应与从 HTTPS 获得的响应不同。HTTP 请求似乎工作正常(在删除RewriteCond
上述指令后),但 HTTPS 请求没有按要求工作。事实上,请求https://example.net/
似乎完全绕过了您的指令。
HTTP 和 HTTPS 之间的这种差异意味着指令在您的服务器配置中的位置不正确,因为 HTTP 和 HTTPS 请求通常由不同的虚拟主机处理。查看您的配置文件后,这确实似乎是问题所在。
您有 2 个<VirtualHost>
容器,一个用于端口 80 (HTTP),另一个用于端口 443 (HTTPS)。上面的 mod_rewrite 指令仅在您的端口 80 虚拟主机中,因此它们仅适用于 HTTP 请求,而不适用于 HTTPS。
我假设您想要规范化请求,以便所有 HTTP 请求都重定向到 HTTPS。
您需要执行以下操作:
- 将上述指令从
<VirtualHost X.X.X.X:80>
容器中移出并放入<VirtualHost X.X.X.X:443>
容器中。您不需要<IfModule mod_rewrite.c>
包装器。 在
<VirtualHost X.X.X.X:80>
容器中(先前包含上述指令)使用 mod-alias 发出 HTTP 到 HTTPS 重定向Redirect
:Redirect 301 / https://example.net/
但是如果你计划实施高速传输系统那么您应该在这里使用 mod_rewrite (重定向到同一主机):
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
(或者...您需要将每个当前虚拟主机拆分为 www 和非 www 版本,而不是只有两个虚拟主机,每个虚拟主机覆盖 www 和非 www。)
因此,你最终会得到如下结果:
indikatrix.net.txt
<VirtualHost X.X.X.X:80>
ServerName example.net
ServerAlias www.example.net
ServerAdmin [email protected]
DocumentRoot /home/example/public_html/
### OTHER DIRECTIVES HERE... ###
# Redirect all requests to HTTP
Redirect 301 / https://example.net/
### OTHER DIRECTIVES HERE... ###
</VirtualHost>
ssl.txt
<VirtualHost X.X.X.X:443>
ServerName example.net
ServerAlias www.example.net
ServerAdmin [email protected]
DocumentRoot /home/example/public_html/
### OTHER DIRECTIVES HERE... ###
RewriteEngine on
# Language redirect...
RewriteCond %{HTTP:Accept-Language} hu [NC]
RewriteRule !^/?hu https://example.net/hu/ [R,L]
RewriteCond %{HTTP:Accept-Language} !hu [NC]
RewriteRule !^/?en https://example.net/en/ [R,L]
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/indikatrix.net.cert
SSLCertificateKeyFile /etc/pki/tls/private/indikatrix.net.key
SSLCertificateChainFile /etc/pki/tls/certs/indikatrix.net.bundle
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
### OTHER DIRECTIVES HERE... ###
</VirtualHost>
不过,还请注意我上面关于潜在逻辑错误并考虑相应地更改上述指令中的正则表达式。
此外,上述内容未涵盖(您的问题中也未解决)的是,对于诸如 这样的请求应该如何处理https://example.net/foo/bar
?目前,这将重定向到https://example.net/hu/
(或/en/
)。这不应该重定向到/hu/foo/bar
(或/en/foo/bar
)吗?
更新#2:
/hu
如果我的浏览器语言是英语,为什么页面会加载?
因为我怀疑你的机器也支持“匈牙利语”。这就是上述“逻辑”的问题所在(如前所述)。Accept-Language
请求标头更复杂,它包含以下形式的字符串:
en-GB,en;q=0.9,hu;q=0.8,id;q=0.7,en-US;q=0.6
即使匈牙利语不是主要语言,如果安装了匈牙利语,则标题中会包含“hu”。您或许可以更改正则表达式以匹配hu
字符串的开头(而不是任何地方)——如上所述。例如:
RewriteCond %{HTTP:Accept-Language} ^hu [NC]
RewriteRule !^/?hu https://example.net/hu/ [R,L]
RewriteCond %{HTTP:Accept-Language} !^hu [NC]
RewriteRule !^/?en https://example.net/en/ [R,L]
但这仍然过于简单了。
- 来自子目录的源现在无法加载(如
<link rel="stylesheet" type="text/css" href="../indikatrix.css"/>
),可能是什么原因?(如果文件位于根目录中)
由于上述指令重定向一切到/hu
或/en
子目录。您需要修改上述指令,以便忽略对现有文件的请求。如果您没有其他需要处理的指令(目前没有),那么您可以在现有指令之前一次性完成此操作:
RewriteCond %{LA-U:REQUEST_FILENAME} -f
RewriteRule ^ - [L]
如果请求映射到现有文件,则处理将停止。您可以优化它,使其仅针对 CSS、JS 和图像(请记住,这意味着 CSS、JS 和图像永远不会被重定向):
RewriteCond %{LA-U:REQUEST_FILENAME} -f
RewriteRule \.(css|js|jpg|png|gif)$ - [NC,L]
你应该避免使用相对的静态资源的路径,以避免将来决定重写 URL 时出现问题。因此,不要使用相对 URL 路径(如)引用文档根目录中的 CSS 文件../indikatrix.css
,而应使用根目录相对路径:/indikatrix.css
。
更新#3:
如果我想加载:
https://example.net/hu
则https://example.net/en
强制。
如果您希望能够覆盖重定向(基于Accept-Lanaguage
标头),则更改RewriteRule
图案适用!^/(en|hu)
于这两条规则。
概括
Options -Indexes -MultiViews
RewriteEngine On
RewriteCond %{LA-U:REQUEST_FILENAME} -f
RewriteRule \.(css|js|jpg|png|gif)$ - [NC,L]
RewriteCond %{HTTP:Accept-Language} ^hu [NC]
RewriteRule !^/(en|hu) https://example.net/hu/ [R,L]
RewriteCond %{HTTP:Accept-Language} !^hu [NC]
RewriteRule !^/(en|hu) https://example.net/en/ [R,L]