1

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]
2
  • %2F is not allowed in Apache unless you have used AllowEncodedSlashes in Apache server config. Commented Aug 14, 2017 at 21:18
  • @anubhava I just enabled that on my dev environment and I'm still getting a 404 Commented Aug 16, 2017 at 4:43

1 Answer 1

2

You can use this rule in your site root .htaccess just below RewriteEngine On line:

RewriteEngine On

# uri with query string    
RewriteCond %{QUERY_STRING}     (?:^|&)(lang=[^&]+) [NC]
RewriteCond %1##%{QUERY_STRING} (.*)##(?:.*&)?uri=([^?]+)(?:\?|%3F)([^&]+) [NC]
RewriteRule lang\.php$ /%2?%1&%3 [L,NE,R=302]

# uri without query string    
RewriteCond %{QUERY_STRING}     (?:^|&)(lang=[^&]+) [NC]
RewriteCond %1##%{QUERY_STRING} (.*)##(?:.*&)?uri=([^?]+) [NC]
RewriteRule lang\.php$ /%2?%1 [L,NE,R=302]
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! I had to change the rule use a question mark in the middle for it to work, like this: RewriteRule lang\.php$ /%2\?%1 [L,NE,R=temporary].
Actually upon further testing I discovered that the ? in the middle only works for URLs without query parameters whereas the & in the middle only works for URLs with query parameters. Is there a way to satisfy both cases? Also the order isn't guaranteed so I duplicated it with the uri first in order to handle that. I hope I don't have to duplicate all of it to handle with and without query params
ok I can tweak these rules further. But you should update question with your existing .htaccess that shows these new set of rules. Also please include a sample URL for each rule so that I can test rules after modifying.
I have modified my question to add sample URLs as well as my attempts using the rule in your solution.
Yes, exactly. The order of the query parameters might be different (as described).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.