Search code examples
apachemod-rewritehttpd.confmod-env

How to write an IF contains condition matching 2 ENV variables set via RewriteRules


To give context, the goal:

Using apache httpd I need to test a contextual segment of the request uri is contained within a cookie value sent in the header before redirect the user to a splash page for cookie confirmation, or allowing them access to the site.

Given the following:

url: http://www.example.com/en/gb/main.html

cookie: ;acceptedCookies=fr,en,de,it

If the language segment of the url = "en", and this is amongst the users acceptedCookies. Then allow the user access to the main site, else redirect the user to the splash page.

What I've tried:

SetEnvIf Host ^ uriCountryCode=NUL
SetEnvIfNoCase Request_URI "^(.+)?\/([a-zA-Z]{2})\/[a-zA-Z]{2}\/.+$" uriCountryCode=$2

SetEnvIf Host ^ acceptedCookieList=EMP 
SetEnvIf Cookie "(^|;\*)acceptedCookies=([^;]+)?" acceptedCookieList=$2
#1st.
<If "%{acceptedCookieList} =~ %{uriCountryCode}">
// Doesn't work
</If>

#2nd.
<If "env('acceptedCookieList') =~ env('uriCountryCode')">
// No luck
</If>

#3rd.
<If "env('acceptedCookieList') =~ /env('uriCountryCode')/">
// Now I'm just guessing
</If>

#4th.
RewriteCond %{acceptedCookieList} !%{uriCountryCode}
RewriteCond %{REQUEST_URI} !^/en/gb/splash.html$ [NC]
RewriteRule ^(.+)$ /mt/en/splash [L,R=301]

I've recently learnt that some of these modules i.e env('x') won't load SetEnvIf variables dues to the SetEnvIf variables not loading early enough to be accessible but i'm trying to find a httpd solution to this my problem


Solution

    1. mod_rewrite can set environment variables.
    2. Use a 302 redirect (Moved Temporarily) instead of a 301 redirect (Moved Permanently).
    3. Matching against an arbitrary regex provided by the client (i.e. the contents of the acceptedCookies cookie) is dangerous. Nevertheless, the httpd expressions language doesn't have a built-in "contains" function and so it's non-obvious how to avoid the regex matching. This will make your server(s) susceptible to DoS attacks.

    All that said, consider something like:

    RewriteCond %{HTTP_COOKIE} acceptedCookies=([^;]+)
    RewriteRule ^.*$ - [E=COOKIE_ACCEPTED_LANGS:%1]
    
    RewriteCond %{REQUEST_URI} ^/([^/]+)/.*$
    RewriteRule ^.*$ - [E=URL_LANG:%1]
    
    RewriteCond expr %{ENV:URL_LANG} =~ %{ENV:COOKIE_ACCEPTED_LANGS}
    RewriteCond %{REQUEST_URI} !^/en/gb/splash.html$ [NC]
    RewriteRule ^.*$ /mt/en/splash [R]