我在将https://www.website.com
重定向到https://website.com
上发表了以下文章:
我无法实现这种重定向,我也不明白是什么原因。
如果我输入https://www.website.com
,它将保留在https://www.website.com
上,并且不执行重定向到https://website.com
的操作。
在使用Apache2的Zope服务器上,我的配置有些特殊。
目前,下面是我的重写规则(http://www.website.com
和http//website.com
都可以正确地重定向到https://website.com
):
<VirtualHost *:443>
# REWRITE to get https://www.website.com to https://website.com except for cgi-bin scripts
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/cgi-bin/search [NC]
RewriteCond %{REQUEST_URI} !^/cgi-bin/awstats [NC]
RewriteRule ^/(.*) https://localhost:8443/++vh++https:%{SERVER_NAME}:443/++/$1 [P,L]
</VirtualHost>
<VirtualHost *:80>
<IfModule mod_rewrite.c>
# www to non www for HTTP and HTTPS
RewriteCond %{REQUEST_URI} ^/www\. [NC,OR]
RewriteCond %{REQUEST_URI} !^/podcast [NC]
# Rewrite below works : redirect 80 => https
RewriteRule ^/(.*) https://website.com/$1 [R=301,L]
RewriteRule ^/(.*) http://localhost:9674/++vh++http:%{SERVER_NAME}:80/++/$1 [P,L]
</IfModule>
</VirtualHost>
这有什么问题吗?
答案 0 :(得分:1)
我相信有few things of note:
一个或多个RewriteCond可以位于RewriteRule指令之前。然后,仅当URI的当前状态都与它的模式匹配并且满足这些条件时,才使用以下规则。
RewriteRule指令......可以多次出现,每个实例定义一个重写规则。定义这些规则的顺序很重要-这是它们在运行时应用的顺序。
在VirtualHost上下文中,模式将首先与主机名和端口之后以及查询字符串之前的URL部分匹配(例如“ /app1/index.html”)。这是(%解码的)URL路径。
如果要与主机名,端口或查询字符串匹配,请分别使用RewriteCond和%{HTTP_HOST},%{SERVER_PORT}或%{QUERY_STRING}变量。
您还使用L|last标志,这使引擎在运行RewriteRule
之后停止处理其他规则。
上面的sorta可以使您了解引擎如何运行您的重写:
RewriteRules
被顺序处理(除非您指定L
标志,否则将对所有规则执行此操作)RewriteRule
可以有许多RewriteCond
,所有这些RewriteRule
必须被考虑,然后再考虑RewriteCond
。这也意味着必须分别为每个RewriteRule
重复VirtualHost
(但是有一个interesting technique会将RewriteRules分组为if-then-else块)HTTP_HOST
上下文),默认情况下仅匹配URL路径,除非您手动匹配<VirtualHost *:80> <!-- your http:// requests will end up with this block, because 80 is the port for http -->
<IfModule mod_rewrite.c>
# www to non www for HTTP and HTTPS <!-- I believe HTTPS traffic is NOT handled by this vhost at all, it arrives straight to *:443 queue -->
RewriteCond %{REQUEST_URI} ^/www\. [NC,OR] <!-- you evaluate path component of your request uri to begin with "www." (i.e. /www.index.html) - this will obviously never match, you however have OR flag, which proceeds to the second condition -->
RewriteCond %{REQUEST_URI} !^/podcast [NC] <!-- you check if the path does not start with "/podcast" - this is easy to test - try http://www.website.com/podcast and see if you get redirected to HTTPS - I suspect you will not -->
# Rewrite below works : redirect 80 => https <!-- I suspect it works by accident, please test it out with http://www.website.com/podcast to confirm my theory -->
RewriteRule ^/(.*) https://website.com/$1 [R=301,L] <!-- we end up here, and regardless of the requested path we issue a 301 redirect to https version of the website. This is marked as Last rule, so the engine should stop processing here -->
RewriteRule ^/(.*) http://localhost:9674/++vh++http:%{SERVER_NAME}:80/++/$1 [P,L] <!-- this I believe kicks in when you request a "/podcast" path - this will proxy the request to your http://localhost:9674/ -->
</IfModule>
</VirtualHost>
<VirtualHost *:443><!-- this is where your 301 redirect will com after bouncing through first set of rules above -->
# REWRITE to get https://www.website.com to https://website.com except for cgi-bin scripts
RewriteEngine On <!-- this is important, keep it on -->
RewriteCond %{REQUEST_URI} !^/cgi-bin/search [NC] <!-- you check whether url path does not contain /cgi-bin/search -->
RewriteCond %{REQUEST_URI} !^/cgi-bin/awstats [NC]<!-- AND does not contain /cgi-bin/awstats-->
RewriteRule ^/(.*) https://localhost:8443/++vh++https:%{SERVER_NAME}:443/++/$1 [P,L]<!-- if both conditions above are met - proxy the request to backend and stop further processing. -->
</VirtualHost>
变量。考虑到这一点,我发现您的重写规则存在一些问题(为了方便阅读,我交换了http和https vhosts,但这并不重要):
https://www.website.com -> https://website.com
据我所知-没有重写/cgi-bin
的规则,https重写要检查的唯一位是<VirtualHost *:443>
RewriteEngine On
# www to non www for HTTPS
<!-- checking for the same thing again -->
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule ^/(.*) https://website.com/$1 [R=301,L] <!-- some people might argue second redirect here is excessive since you already arrived at correct host, but I'd leave this for you to sort out -->
<!-- your /cgi-bin checks can be merged into one regex -->
RewriteCond %{REQUEST_URI} !^/cgi-bin/(search|awstats) [NC]
RewriteRule ^/(.*) https://localhost:8443/++vh++https:%{SERVER_NAME}:443/++/$1 [P,L]
</VirtualHost>
<VirtualHost *:80>
<IfModule mod_rewrite.c>
# www to non www for HTTP
<!-- if you want to keep your `/podcast` on http check it first -->
RewriteCond %{REQUEST_URI} !^/podcast [NC]
RewriteRule ^/(.*) http://localhost:9674/++vh++http:%{SERVER_NAME}:80/++/$1 [P,L]
<!-- everything else will get redirected to https -->
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule ^/(.*) https://website.com/$1 [R=301,L]
</IfModule>
</VirtualHost>
我的建议如下:(这可能不是复制粘贴解决方案,但希望您能理解要点)
{{1}}