Forum Moderators: phranque

Message Too Old, No Replies

Rewrite 'the other way round'

rewrite variable to pretty url.

         

harmhero

3:07 pm on Oct 7, 2011 (gmt 0)

10+ Year Member



OK here goes, my first post on this board :) I called it 'the other way round' because I couldn't think of any other way to put it.

I have a multilanguage site which for years was structured like this:

www.domain.com ->usa
www.domain.com/?country=FR -> france
www.domain.com/?country=DE -> Germany
etc.

Now I have changed everything (except USA) to:
fr.domain.com
de.domain.com

.htaccess:
#HOMEPAGE FR
RewriteCond %{HTTP_HOST} ^fr\.domain\.com
RewriteRule ^$ /index.php?country=FR [L]

#HOMEPAGE DE
RewriteCond %{HTTP_HOST} ^de\.domain\.com
RewriteRule ^$ /index.php?country=DE [L]

Works great! But the searchengines still have www.domain.com/?country=FR indexed. So how can I rewrite this to the new URL?

This doesn't work:

RewriteCond %{REQUEST_URI} ^country=FR
RewriteRule ^(.*)
http://fr\.domain\.com
[L]


I have no idea how to accomplish this. Any ideas?

harmhero

3:46 pm on Oct 7, 2011 (gmt 0)

10+ Year Member



I already figured out that this:

#HOMEPAGE FR
RewriteCond %{QUERY_STRING} ^country=FR$
RewriteRule ^$
http://fr.domain.com/
[R=301,L]

does more, but outputs: fr.domain.com/?country=FR

g1smd

6:57 pm on Oct 7, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This new rule does not rewrite, it REDIRECTS. That is the correct thing to do.

Add a question mark to the target URL in the rule to strip the query string in the redirect.


The "redirect parameter-based URLs to SEF URLs" and "rewrite SEF URLs to internal filepaths" question is asked almost every day here. There are tens of thousands of previous threads explaining this method. Read a few dozen of them to get the full picture.

harmhero

7:05 pm on Oct 7, 2011 (gmt 0)

10+ Year Member



that did it

RewriteCond %{QUERY_STRING} ^country=FR$
RewriteRule ^$ [fr.domain.com...] [R=301,L]

Thanks. I knew it had to be covered, I just don't know how to search due lack of knowledge of the right jargon I guess. Now I know, thanks g1smd!

g1smd

7:22 pm on Oct 7, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Be aware that this method can sometimes create an infinite rewrite-redirect-rewrite loop.

In a much simpler example:
Request:
example.com/index.php

Path matches rule pattern and redirects to:
example.com/

Request:
example.com/

Internally rewrite to:
/index.php

Path matches rule pattern and redirects to:
example.com/

Request:
example.com/

Internally rewrite to:
/index.php

... etc.

In that case, the redirect RewriteCond should test THE_REQUEST for parameters being present, not QUERY_STRING. This is to be sure that the parameters are present in the original URL request and not as the result of a previous internal rewrite.

harmhero

9:30 am on Oct 8, 2011 (gmt 0)

10+ Year Member



If I change it to:

RewriteCond %{THE_REQUEST} ^country=FR$
RewriteRule ^$ [fr.domain.com...] [R=301,L]

it doesn't work and outputs www.domain.com/?country=FR

g1smd

5:55 pm on Oct 8, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The rule condition will never match because THE_REQUEST will be presented with:

GET /?country=FR HTTP/1.1

OR
GET /index.php?country=FR HTTP/1.1


as sent in the original HTTP request.

Your RegEx pattern is looking for something that begins "country" and ends "FR". The browser actually sends something else. Your RegEx pattern is incorrect.

harmhero

2:22 pm on Oct 9, 2011 (gmt 0)

10+ Year Member



OK I changed it to:

RewriteCond %{THE_REQUEST} country=FR
RewriteRule ^$ [fr.example.com...] [R=301,L]

lucy24

6:23 pm on Oct 9, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



As written: "If there is a null request (^$ with nothing between) with a query string that includes "country=FR" (a [NC] flag is probably a good idea) then redirect the user to fr.example.com."

Do you want everyone to go to the subdomain? If so, you can say

RewriteRule .* et cetera

Ordinary humans are not likely to send null requests (I think g1 said it depends on the http version, and not many humans use 1.0) but may as well cover all possibilities. If you want to get all requests, but you're not capturing them for reuse, you don't need anchors.

All non-null requests:

.+

All requests for top-level index file only:

^/?$

harmhero

6:45 pm on Oct 9, 2011 (gmt 0)

10+ Year Member



so, since this only applies to the homepage, I changed it to:


#homepage
RewriteCond %{THE_REQUEST} country=FR [nc]
RewriteRule ^/?$ http://fr.example.com/? [R=301,L]


the other pages:

#other pages
RewriteCond %{THE_REQUEST} country=FR [nc]
RewriteRule ^(.*)\.php$ http://fr.example.com/$1.php? [L]

g1smd

8:49 pm on Oct 9, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



In per-directory context, as used in
.htaccess
, the leading folder names and the trailing slash are stripped before being presented to the RegEx parser.

So, a request for "this" folder will be matched by the pattern ^$ or !. as you please.

The pattern ^/?$ is not correct. It matches requests for
example.com/
and
example.com//
alike.

The pattern
^(.*)\.php$
is very ineffficent. Never use (.*) at the beginning of a pattern.

For only root use
^([^/.]+)\.php$


For any depth of folder use
^(([^/]+/)*[^/.]+)\.php$

harmhero

9:29 pm on Oct 9, 2011 (gmt 0)

10+ Year Member



Thanks for the feedback. Talking about efficiency, because my file- and DB structure is unfortunately set up with capital letters (as in country=FR), it seems impossible to join all requests. So for every country I have to make:

#MENU AU
RewriteCond %{HTTP_HOST} ^au\.example\.com
RewriteRule ^([^/.]+)\.php$ $1.php?country=AU [L]

#MENU DE
RewriteCond %{HTTP_HOST} ^de\.example\.com
RewriteRule ^([^/.]+)\.php$ $1.php?country=DE [L]


...and the other 10 countries. I cannot use RewriteMap lc int:tolower since I don't have access to httpd.conf

g1smd

9:50 pm on Oct 9, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Unless you want your server hacked, you MUST add a leading slash to the target filepath immediately before the $1 part.

You should also check whether requests for
www.CC.example.com
resolve, and if they do, what response is returned.

harmhero

10:10 pm on Oct 9, 2011 (gmt 0)

10+ Year Member



the leading slash before $1 gives me error 500. But I had to change:

rewriteRule ^([^/.]+)\.php$ $1.php?country=DE [L]
in:
rewriteRule ^(menupage|menupage2|menupage3)\.php$ $1.php?country=DE [L]

otherwise I had some conflicts with a .php which has lots of variables.

g1smd

10:36 pm on Oct 9, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If you want to leave your server open to a hack that is loosely related to this one [contextis.com...] then begin the target with $1 and no leading folder data.

If you want to fix it, add at least a slash before it; the exact path may actually include some folder names.

Beware of creating an infinite rewrite loop. You may need a preceding negative match RewriteCond that excludes previously rewritten requests from being rewritten again.

harmhero

10:55 pm on Oct 9, 2011 (gmt 0)

10+ Year Member



...but this slash before $1 gives me an error 500:

rewriteRule ^(menupage|menupage2|menupage3)\.php$ /$1.php?country=DE [L]

lucy24

4:05 am on Oct 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Under normal circumstances, the slash should give you a 500 error. Or lead to an unwanted redirect, depending on details that are beyond your control.

If you don't have access to the config file then I assume you are on shared hosting. Ask them about the proxy/security issue. It's in their power to fix it. (And if you get an answer along the lines of "Don't worry your pretty little face about that"-- change hosts! :))

Also take a quick look at your error logs; they tend to be pretty helpful about 500 errors. Much more than with 403's where it just says "client denied by server configuration" and you have to rack your brains trying to remember why you locked them out. Especially if your lockout was based on something like referer or UA that isn't shown in the error logs.

lucy24

5:22 am on Oct 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



### and ### that clock. That's, er, pretty little head. Oops.