Apache mod_alias RedirectMatch all but a specific pattern

Good old regular expressions infuriate me.

I need to redirect all traffic in Apache 2.4 from HTTP to HTTPS, with the exception of "/ bt / sub / [a_few_endings]", using Redirect from mod_alias (can't use mod_rewrite).

I tested the following regular expression in all tested online testers (e.g. http://regex101.com/ ) and everyone confirms that the regular expression should really match all but the URLs that I don't want them to match:

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

As far as I can tell, this should match everyone at http : //local.mysite.com and redirect it to https : //local.mysite. com, with the exception of the following four:

However, Apache redirects everything, including the above URLs, which I do not want to redirect.

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, but those that people say did not work for me.

Here is my virtual host configuration, as it stands now:

 <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 stop me from going crazy :)


UPDATE: Something strange happens there: obviously, when the requested URL / path can be found, Apache ignores the expression in RedirectMatch and redirects the client, although RedirectMatch does not report this.

To test this, I created a new virtual host from scratch inside a separate virtual machine recently installed with Ubuntu Trussty 64, loaded with Apache 2.4. This new virtual host contained only ServerName, RedirectMatch, and DocumentRoot directives, for example:

 <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 that Apache can get at least one of two possible URLs. When I try to access http://testing.com:8080 , I get a redirect, as expected.

Then a strange thing arises: when accessing http://testing.com:8080/bt/sub/went_active , the URL that corresponds to the directory I created is still redirected, although I should not be, but when accessing http://testing.com:8080/bt/sub/success I do not redirect and instead get a forbidden 403.

I may lose my mind about this, but it seems that when Apache sees that it can serve as a request and it matches the regular expression in RedirectMatch, which should prevent redirection, it decides to ignore the regular expression and redirect anyway, Three letters for of this: WTF?!?!?!

+5
source share
2 answers

As mentioned in the comments, this is easier to do with mod_rewrite . Possible solutions

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

Another (for .htaccess, since the initial / is removed from the RewriteRule )

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

And the RedirectMatch solution

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

Everything works fine, the problem that may arise in the testing / debugging state is that the browser caches the response 301 . So, when you try to check or write the correct code, use the 302 answer, not 301 . And remove the NC flag if case insensitivity is not required.

+8
source

See this

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

A match / followed by something, unless the end of the line is preceded by / foo / bar / (aaaa | bbb ...)

(?<! is a negative lookbehind attached to the end of the string $ , which will make it impossible to match what is inside just before the end of the string.

If your real case is not as static as your example, give real data for part of the request.

+1
source

Source: https://habr.com/ru/post/1204807/


All Articles