所以我有这个疯狂的问题发生在apache 2.4 / CentOS7上的一个web应用程序。
我想redirect应用程序域上的所有非安全的URL到安全版本,除了一个uri(供应商沙箱模式的webhook端点 – 没有有效的SSL证书,因为这不是生产,所以我们必须允许http)。 除了应用程序域之外,还有一些客户站点域也贯穿于此,所以我们不希望那些redirect,因为没有SSL,所以我们明确地匹配HTTP_HOST。
这是一个前端控制器模式,我们希望index.php将所有这些请求处理到所有域的非文件和非目录,以及仅通过应用程序域的SSL。
它很简单:
RewriteEngine on RewriteBase "/" # Redirect all app domain urls to ssl RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} "^app\.example\.com$" [NC] RewriteCond %{REQUEST_URI} "!^/AllowThisUri/Http" RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # I had to split this -d rule off of the -f rule to account for custom # domain homepages from not being routed to the front controller when # transitioning from centos6/apache2.2 for some reason RewriteCond %{REQUEST_FILENAME} -d RewriteCond %{REQUEST_URI} "!^/$" RewriteRule "^(.*)$" index.php [L] # Redirect non-files to entry script RewriteCond %{REQUEST_FILENAME} !-f RewriteRule "^(.*)$" index.php [L]
但是当我testing时发生了什么
curl http://app.example.com/AllowThisUri/Http
传递给index.php的最后一条规则正在被使用,而不是实际上由index.php处理,它正在redirect那里… curl返回(缩短的响应)
<title>301 Moved Permanently</title> <p>The document has moved <a href="https://app.example.com/index.php">here</a>.</p>
所以如果我注释掉这个新的排除RewriteCond:
#RewriteCond %{REQUEST_URI} "!^/AllowThisUri/Http"
预期的事情发生,它redirect到相同的URL,除了https:
<title>301 Moved Permanently</title> <p>The document has moved <a href="https://app.example.com/AllowThisUri/Http">here</a>.</p>
如果我完全删除redirect到https逻辑,我确实得到了我期望的前端控制器的响应(它只是打印'嗨'进行testing)。
#RewriteCond %{HTTPS} off #RewriteCond %{HTTP_HOST} "^app\.example\.com$" [NC] #RewriteCond %{REQUEST_URI} "!^/AllowThisUri/Http" #RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
所以我把它全部放回原来的位置 – 我可以像这样修改R = 301到302:
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
并且确定它改变了不好的意外的redirect响应:
<title>302 Found</title> <p>The document has moved <a href="https://app.example.com/index.php">here</a>.</p>
我希望这是有道理的。 这是啰嗦解释,我很抱歉。
我看到的是即使!^ / AllowThisUri / Http条件匹配,我们跳过了httpsredirect规则,并且规则继续处理,直到它到达最后一条将它发送到index.php的规则,就像redirect部分规则IT SKIPPED似乎挂在某处,并影响结果。 这对我来说绝对没有意义。
重申一下,如果不用一个RewriteCond排除一个uri,那么非ssl到ssl的redirect就如预期那样工作。 为了完全删除所有的redirect逻辑,index.php前端控制器响应期望的响应。 当我们添加这一个额外的RewriteCond来排除一个uri,它以不正确的/意外的方式行事,并且返回一个redirect到index.php而不是被处理,并且从前端控制器返回期望的响应。
也许有人知道一些晦涩的设置或可能是一个Apache 2.4的事情会导致这个?
谢谢你的时间。