9

好的旧正则表达式让我发疯。

我需要使用从 mod_alias 重定向(不能使用 mod_rewrite)将 Apache 2.4 中的所有流量从 HTTP 重定向到 HTTPS,“/bt/sub/[a_few_endings]”除外。

我在我认识的所有在线测试人员(例如http://regex101.com/)中测试了以下正则表达式,并且都确认正则表达式确实应该匹配除了我不希望它匹配的 URL 之外的所有内容:

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

据我所知,这应该匹配http://local.mysite.com中的所有内容并将其重定向到https://local.mysite.com以下四个除外:

尽管如此,Apache 还是会重定向所有内容,包括我不想重定向的上述 URL。

我在 SO 中发现了几个类似的问题,但大多数问题都是根据 mod_rewrite 来回答的,这不是我想要/需要的,人们说的那些对我不起作用。

这是我目前的虚拟主机配置:

<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>

请帮助并防止我发疯:)


更新:发生了一些奇怪的事情:显然,当可以找到请求的 URL/路径时,Apache 会忽略 RedirectMatch 中的表达式并重定向客户端,即使 RedirectMatch 告诉它不要这样做。

为了测试这一点,我在一个单独的虚拟机中从头开始创建了一个新的虚拟主机,该虚拟机新安装了 Ubuntu Trussty 64,加载了 Apache 2.4。这个新的虚拟主机只包含 ServerName、RedirectMatch 和 DocumentRoot 指令,如下所示:

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

    DocumentRoot /home/vagrant/www
</VirtualHost>

我创建了该目录/home/vagrant/www/bt/sub/went_active以确保 Apache 至少可以访问两个可能的 URL 之一。尝试访问http://testing.com:8080时,我按预期被重定向。

然后奇怪的是:当访问http://testing.com:8080/bt/sub/went_active与我创建的目录匹配的 URL 时,我仍然被重定向,即使我不应该这样做,但是在访问时http://testing.com:8080/bt/sub/success,我没有被重定向,而是得到一个 403 Forbidden。

我可能对此失去理智,但似乎当 Apache 看到它可以服务请求并且它匹配 RedirectMatch 中应该阻止重定向的正则表达式时,它决定忽略正则表达式并无论如何都进行重定向。三个字母:WTF?!?!?!

4

2 回答 2

10

正如评论中所说 - 它更容易使用mod_rewrite. 可能的解决方案

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

另一个(对于 .htaccess,初始/值已从 中删除RewriteRule

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

和解决方案RedirectMatch

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

一切正常,您在测试/调试状态下可能遇到的问题是浏览器缓存301响应。因此,当您尝试检查或编写正确的代码时,请使用302响应,而不是301. NC如果不需要不区分大小写,则删除标志。

于 2014-10-16T19:41:11.860 回答
1

看到这个

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

匹配 / 后跟任何内容,除非字符串的结尾以 /foo/bar/(aaaa|bbb...)

(?<!是一个附加到字符串末尾的负向lookbehind $,它将检查它不可能匹配字符串末尾之前的内容。

如果您的真实案例不像您的示例那样静态,请为查询部分提供真实数据。

于 2014-10-16T09:10:47.507 回答