My application used to do language switching using a lang.php
file. A URL to redirect to English for /path/to/page.php?foo=bar
would look like this:
/path/to/lang.php?lang=en-CA&uri=%2Fpath%2Fto%2Fpage.php%3Ffoo%3Dbar
Recently there has been some changes to accept a lang
query parameter on all pages. So this URL is nicer:
/path/to/page.php?foo=bar&lang=en-CA
I'd like to be able to add a .htaccess file to all the locations that I have a lang.php
file in order to keep the existing URL working without the lang.php
file. Is this possible?
The RewriteRules must be completely relative to lang.php as the application is running on different hostnames and paths.
I took a stab at it based on the answer here but this is giving me a 404:
RewriteCond %{REQUEST_FILENAME} lang.php$
RewriteCond %{QUERY_STRING} (?:^|&)uri=([^&]+) [NC]
RewriteRule lang.php - [E=LANG_REDIR_URI:%1]
RewriteCond %{REQUEST_FILENAME} lang.php$
RewriteCond %{QUERY_STRING} (?:^|&)lang=([^&]+) [NC]
RewriteRule lang.php - [E=LANG_REDIR_LANG:%1]
RewriteCond %{REQUEST_FILENAME} lang.php$
RewriteRule . %{LANG_REDIR_URI}e [L,R=temporary]
The uri
parameter may already have query parameters (as in the examble above), and the code should not make the application vulnerable to an open redirect vulnerability.
Different cases:
- URI with query string, lang first:
/foo/bar/lang.php?lang=en-CA&uri=%2Ffoo%2Fbar%2Fpage.php%3Fid%3D123
should redirect to/foo/bar/page.php?id=123&lang=en-CA
- URI without query string, lang first:
/foo/bar/lang.php?lang=en-CA&uri=%2Ffoo%2Fbar%2Fpage.php
should redirect to/foo/bar/page.php?lang=en-CA
- URI with query string, uri first:
/foo/bar/lang.php?uri=%2Ffoo%2Fbar%2Fpage.php%3Fid%3D123&lang=en-CA
should redirect to/foo/bar/page.php?id=123&lang=en-CA
- URI without query string, uri first:
/foo/bar/lang.php?uri=%2Ffoo%2Fbar%2Fpage.php&lang=en-CA
should redirect to/foo/bar/page.php?lang=en-CA
The order of the query parameters do not matter in the redirect target.
UPDATE
After the initial answer provided at https://stackoverflow.com/a/45732670/404623, I've tried the following .htaccess rules:
# This only works for uri values without query strings
RewriteCond %{QUERY_STRING} ^(lang=[^&]+)&uri=([^&]+) [NC]
RewriteRule lang\.php$ /%2\?%1 [L,NE,R=temporary]
RewriteCond %{QUERY_STRING} ^uri=([^&]+)&(lang=[^&]+) [NC]
RewriteRule lang\.php$ /%1\?%2 [L,NE,R=temporary]
# This only works for uri values with query strings
RewriteCond %{QUERY_STRING} ^(lang=[^&]+)&uri=([^&]+) [NC]
RewriteRule lang\.php$ /%2&%1? [L,NE,R=temporary]
RewriteCond %{QUERY_STRING} ^uri=([^&]+)&(lang=[^&]+) [NC]
RewriteRule lang\.php$ /%1&%2? [L,NE,R=temporary]