简体   繁体   English

Apache mod_alias RedirectMatch除特定模式之外的所有内容

[英]Apache mod_alias RedirectMatch everything except specific pattern

Good old regular expressions are driving me nuts. 好的旧正则表达式让我疯狂。

I need to redirect all traffic in Apache 2.4 from HTTP to HTTPS, except for "/bt/sub/[a_few_endings]", using Redirect from mod_alias (can't use mod_rewrite). 我需要将Apache 2.4中的所有流量从HTTP重定向到HTTPS,除了“/ bt / sub / [a_few_endings]”,使用来自mod_alias的重定向(不能使用mod_rewrite)。

I tested the following regular expression in all online testers I know (eg http://regex101.com/ ) and all confirm that the regex should indeed match everything except the URLs I don't want it to match: 我在我认识的所有在线测试人员中测试了以下正则表达式(例如http://regex101.com/ )并且都确认正则表达式确实应该匹配除了我不希望它匹配的URL之外的所有内容:

^/(?!bt/sub/(went_active|success|cancel|expired)).*$ 

As far as I can tell, this should match everything in http ://local.mysite.com and redirect it to https ://local.mysite.com, except for the following four: 据我所知,这应该与HTTP 的一切 ://local.mysite.com并将其重定向到https://local.mysite.com, 除了以下四种:

Still, Apache redirects everything, including the above URLs I don't want redirected. 仍然,Apache重定向所有内容,包括我不想重定向的上述URL。

I found several similar questions in SO but most of them are answered in the light of mod_rewrite, which is not what I want/need, and the ones that people say have worked have not worked for me. 我在SO中发现了几个类似的问题,但大多数都是根据mod_rewrite回答的,这不是我想要/需要的,人们说有用的那些对我没用。

Here's my virtual host configuration as it currently stands: 这是我目前的虚拟主机配置:

<VirtualHost *:80> 
    ServerName local.mysite.com 
    RedirectMatch 302 ^/(?!bt/sub/(went_active|success|cancel|expired)).*$ https://local.mysite.com 
    DocumentRoot /home/borfast/projects/www/mysite/public 
    #Header set Access-Control-Allow-Origin * 
    SetEnv LARAVEL_ENV localdev 

    <Directory /home/borfast/projects/www/mysite/public/> 
        Options All 
        DirectoryIndex index.php 
        AllowOverride All 
        Require all granted 
    </Directory> 
</VirtualHost>

Please help and prevent me from going crazy :) 请帮助,防止我发疯:)


UPDATE: There's something weird going on: apparently when the requested URL/path can be found, Apache ignores the expression in RedirectMatch and redirects the client, even though the RedirectMatch tells it not to. 更新:有一些奇怪的事情:显然当找到请求的URL /路径时,Apache忽略RedirectMatch中的表达式并重定向客户端,即使RedirectMatch告诉它不要。

To test this I created a new virtualhost from scratch inside a separate VM freshly installed with Ubuntu Trussty 64, loaded with Apache 2.4. 为了测试这一点,我在一个单独的VM中创建了一个新的虚拟主机,该虚拟主机安装了新的Ubuntu Trussty 64,并装载了Apache 2.4。 This new virtual host contained just the ServerName, RedirectMatch and DocumentRoot directives, like this: 这个新的虚拟主机只包含ServerName,RedirectMatch和DocumentRoot指令,如下所示:

<VirtualHost *:80>
    ServerName testing.com
    RedirectMatch 302 ^/(?!bt/sub/(went_active|success)$).*$ https://othersite.com/

    DocumentRoot /home/vagrant/www
</VirtualHost>

I created the directory /home/vagrant/www/bt/sub/went_active to make sure Apache could get to at least one of the two possible URLs. 我创建了目录/home/vagrant/www/bt/sub/went_active以确保Apache可以访问两个可能的URL中的至少一个。 When trying to access http://testing.com:8080 , I get redirected, as expected. 当试图访问http://testing.com:8080 ,我按预期重定向。

Then the weirdness comes: when accessing http://testing.com:8080/bt/sub/went_active , the URL that matches the directory I created, I am still redirected, even though I shouldn't be, but when accessing http://testing.com:8080/bt/sub/success , I don't get redirected and instead get a 403 Forbidden. 然后奇怪的是:当访问http://testing.com:8080/bt/sub/went_active ,与我创建的目录匹配的URL时,我仍然被重定向,即使我不应该,但是在访问http://testing.com:8080/bt/sub/success ,我没有被重定向,而是获得403 Forbidden。

I may be losing my sanity over this but it seems that when Apache sees that it could serve the request and it matches the regular expression in RedirectMatch that should prevent the redirect, it decides to ignore the regular expression and do the redirect anyway. 我可能会对此失去理智,但似乎当Apache发现它可以提供请求并且它与RedirectMatch中的正则表达式匹配时应该阻止重定向时,它决定忽略正则表达式并进行重定向。 Three letters for this: WTF?!?!?! 三封信:WTF?!?!?!

As it was said in comments - it is easier to do with mod_rewrite . 正如在评论中所说的那样 - 使用mod_rewrite更容易。 Possible solutions 可能的解决方案

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/bar/(abcd|baz|barista|yo)$ [NC]
RewriteRule ^ http://site/ [R=301,L]

Another one (for .htaccess, as initial / is removed from RewriteRule ) 另一个(对于.htaccess,作为初始/RewriteRule删除)

RewriteEngine On
RewriteRule !^bar/(abcd|baz|barista|yo)$ http://site/ [R=301,L,NC]

And solution by RedirectMatch RedirectMatch解决方案

RedirectMatch permanent ^(?!/bar/(abcd|baz|barista|yo)$).* http://site/

All work perfectly, the problem that you might have on a testing/debugging state is that browser caches 301 response. 一切都很完美,你在测试/调试状态下可能遇到的问题是浏览器缓存301响应。 So, when you are trying to check or to write the correct code - use 302 response, not 301 . 因此,当您尝试检查或编写正确的代码时 - 使用302响应,而不是301 And remove NC flag if case insensitivity is not required. 如果不需要不区分大小写,请删除NC标志。

See this one 看到这个

^\\/.*(?<!foo\\/bar\\/(aaa|bbb|ccc|ddd))$

Match / followed by anything, unless the end of string is preceded by /foo/bar/(aaaa|bbb...) 匹配/后跟任何东西,除非字符串的结尾前面是/ foo / bar /(aaaa | bbb ...)

The (?<! is a negative lookbehind attached to end of string $ which will check its impossible to match what's inside just before the end of string. (?<!是附加到字符串$结尾的负向lookbehind,它将检查它不可能匹配字符串结束之前的内部。

If your real case is not as static as your exemple, give real datas for the query part. 如果您的实际情况不像示例那样静态,请为查询部分提供实际数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM