Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Get the referer URL from a 301 redirect 1

Status
Not open for further replies.

glimbeek

Programmer
Nov 30, 2009
83
0
0
NL
I have a website:

with several different languages aka:
example.com/us/
example.com/uk/
example.com/de/
example.com/fr/
etc...

Based on your IP, using a GeoIP script, you are pointed towards the right language except for languages from the EU (except UK). Those are done based upon the browser language.

Recently we "removed" /us/ and using .htaccess we 301 it to which works fine.
But after the 301 rewrite, the GeoIP script still checks for your browser language (because the script didn't rewrite you yet). If you for instance use a browser with the language set to German and you browse to the following happends:
301 to 302 to (based upon the browser language).

Obviously this isn't something you want so I'm trying to "fix" it.

All though I'm lost on how to fix it. I looked into using HTTP_REFERER, but that isn't to be trusted (according to the PHP manual) + it doesn't seem to work in this instance. The HTTP_REFERER stays empty?

Two questions:

1) What's the cleanest rewrite to rewrite /us/?
RewriteRule ^us$ [NC,OR]
RewriteRule ^us/$ [NC,R=301,L]

Does that come close? Or is there a better way?

2) Does anybody know a way to check where the visitor came from (the 301 redirect) so I can make sure my script doesn't 302 the visitor after the 301?

Thanks in advance!

With kind regards,
George
 
how about this ...

redirect to a script that has the following

Code:
<?php
session_start();
$_SESSION['lang'] = 'en';
session_write_close();
header('Location: [URL unfurl="true"]http://www.example.com');[/URL]
exit;
?>

then in your code do the following
Code:
<?php
session_start();
if (isset($_SESSION['lang']) && $_SESSION['lang'] == 'en'){
  //do nothing
} else {
  //process the geoIP script
}
//normal script processing
 
The first rewrite is done by .htaccess. So making a php check after the first rewrite to rewrite again still leaves me with 2 rewrites where there should be one.

Isn't there a way to get the URL where someone came from eg. exmaple.com/us/? Or to get the 301 header from the rewrite?
 
you would need to check with the apache forum. this will be server dependent and will have nothing to do with php. any data that the server makes available will be accessible in php via the environmental vars.
 
let me ask another quick question.

in the example you gave (someone with a german browser and addressing example.com/us/ what is it you want to happen?
 
For instance someone with a German browser:
If they visit example.com/us/ they get 301 rewritten, using .htacces, to example.com/ and then nothing should happen.

If they visit example.com/ they should get 302 rewritten to example.com/de/ using PHP header();
 
assuming you are trusting only the accept-language header that browsers provide you could do something like this

Code:
RewriteEngine ON

# if the browser accepts english as preferred AND the user is at a subdirectory of [URL unfurl="true"]www.example.com,[/URL] redirect permanently to [URL unfurl="true"]www.example.com[/URL]

RewriteCond %{HTTP:Accept-Language} ^en [NC]
RewriteRule ^/(es|de|fr)/.*$ [URL unfurl="true"]http://www.example.com[/URL] [L,R=301]

#if the browser accepts any of spanish, french and german as preferred AND the site is not at [URL unfurl="true"]www.example.com[/URL] then redirect permanently to [URL unfurl="true"]www.example.com/LANG[/URL]
RewriteCond %{HTTP:Accept-Language} ^es [NC,OR]
RewriteCond %{HTTP:Accept-Language} ^fr [NC,OR]
RewriteCond %{HTTP:Accept-Language} ^de [NC]
RewriteRule ^$ [URL unfurl="true"]http://www.example.com/%{HTTP:Accept-Language}/[/URL] [L, R=301]


#deal with some default position or just don't rewrite

i am not an expert at all of things to do with apache so you will quite probably get a better answer from the cross-post.
 
So you suggest rewritting just with .htaccess?

How does this work with someone browsing from Japan for instance? They should get the default English page if they browse to example.com/.

If they browse to example.com/us/ they should get the 301 rewrite to example.com/

"# if the browser accepts english as preferred AND the user is at a subdirectory of redirect permanently to
And if they are in example.com/news/ or example.com/de/news/ they shouldn't get rewritten to example.com/. Keeping this in mind example.com/us/news/ for instance never existed. example.com/us/ is the only US page there is.
 
you are changing the goal posts. I tried to provide a solution to the scenario that you posed in your post of 10 Jun 2010 @ 2:08. If you provide the universe of possible matches and required rewrites then we can possibly come up with a solution. Without this we can only guess at your requirements.

if the user prefers english language and browses to then he will get redirected to (where *** is a language that you explicitly support - cf the regex of (es|de|fr))

if the user browses to and his browser language preference is one that you explicitly supports, the user will be redirected to lang/

If you do not support japanese and someone browses to then no redirect will occur.

will not redirect anywhere. exactly the same as the jp example.
will redirect to if the user's browser preference is one that you expressly support and german is the set preference.

if you want to stop the last redirect example you will need to add in tests to make sure that the match does not attach to the preferred language. you can do this with complex OR and L flags or by using negative look aheads. i would use the latter method for cleanliness.

if you want to redirect to when the preferred language is spanish, then you would need to incude some capturing parenthetics in the rewrite rule and the relevant back reference in the rewritten url.
 
I might have not made myself clear enough. And by the looks of your reply, it looks like you are misunderstanding me.

All the rewrite examples your are giving are not needed.
Nor does someone from Japan get redirect to example.com/jp/ nor does that page exist.

I just gave it as an example to figure out if your solution worked if someone from Japan would browse to my website.

To explain myself better:
The language specific 302 rewrite is done by a GeoIP script AFTER the 301 rewrite, done the by the .htaccess file. This 301 rewrite ONLY happens IF someone browses to example.com/us/.
So if someone browses to example.com/us/ they are 301 rewritten to example.com THEN the GeoIP script kicks in. "All" I'm looking for is a way for me to check with PHP if someone came from example.com/us/ so I know not to run the GeoIP script.

I apologize if I made a mess out of the first post, I tried to be as clear as possible about my problem and the solution I am looking for.
 
i think it best if you show us your geoIP script. the htaccess rules that i provided would, when filled out, provide a complete language rewriting system that would obviate the need for simple IP sniffing if the choice were related to language rather than location

in answer to your 'ALL' question in your redirect for example.com/us/ add a query string parameter to tell php (in the $_GET superglobal) that this is a redirect. you can then test for this in your geoIP script.
 
I forgot to mention one thing in my last post:
For people from Great Brittain AKA the UK we base the "language" of what they see (where they go to: example.com/uk/, if the browse to example.com/ on their first visit) on IP.
For other languages on the site:
fr, de, tr, nl - We use the browser language.

Isn't $_SERVER['HTTP_REFERER']; a super global? The PHP manual says that you can't trust REFERER.

The GeoIP script is the script from with the addition on a check on browser language. It's nothing fancy. If only I could figure out a way to see where a visitor came from I can then run my GeoIP script. or not. Not being the case if a visitor went straight to example.com/us/ and they got 301 rewritten to example.com/ by my .htaccess file.
 
HTTP_REFERER is browser optional. your user can control what is sent in the referer field, or even turn it off. You cannot trust that the variable is there, is populated or is populated with the correct value. That is why php says that you cannot trust it. You are correct that, if present, it is populated as part of the $_SERVER superglobal.

from what you say I suppose the following use cases

1. if the browser language preference is one of fr/de/tr/nl you do not use any geoIP sniffing and redirect the user to specific subdirectories of your site, if they are not already there.

2. the browser language preference is anything else then you redirect to
3. all visitors to are geosniffed on their first visit. if their ip is one in fr/de/tr/nl you redirect back to the relevant subdirectory. if their ip is anything else you show them english standard content.

If the above is correct, I can see a single script way to do all of this within php. i can also see a way to do this with a combination of .htaccess and geoip but there is no way to avoid the potential of a second redirect. ... unless you are willing to adjust your php architecture fractionally (so that lots hangs off the initial sniffer script).

i personally would construct this type of activity with everything pointing towards and not performing any redirects. just use php to sniff and serve as needeed.
 
Thanks for the support!

jpadie,

I'd still prefer to rewrite example.com/us/ to example.com using .htaccess and not do this with PHP.

Isn't there a way to check with PHP where someone came from, other then REFERER?
 
Hi

glimbeek said:
Isn't there a way to check with PHP where someone came from, other then REFERER?
What about redirecting example.com/us/ to example.com/?us ? That way the path not contains "us/", but your script ( and rewrite rule if necessary ) will know that a redirection was performed and can deduce what was the original request.

As HTTP protocol is stateless, it offers no mechanism to bind consecutive requests logically together. That is why session handling mechanisms are implemented in the CGI languages. I would do as jpadie suggested : use a tiny PHP script to redirect and save the related information in the session.

Feherke.
 
Code:
Isn't there a way to check with PHP where someone came from, other then REFERER?

not in the way that you are trying to achieve this (i.e. without engaging a server side language), no. Which is why I have been suggesting alternatives.

another alternative which might fit your bill is that perhaps you could add a nocheck GET variable to the first redirect? you could do this from within htaccess and check for it from within htaccess.
 
How do add a "nocheck GET variable to the first redirect?" ps. it's a rewrite not a redirect.

I never heard of such a thing.
 
last post, because this is not php and therefore has no business here.

Code:
RewriteRule ^$ [URL unfurl="true"]http://www.example.com/%{HTTP:Accept-Language}/[/URL] [L, R=301]
this is a rewrite. ^$ means match anything and the next bit tells it what the new rewritten url should be.

to add a no check you would do this
Code:
RewriteRule ^$ [URL unfurl="true"]http://www.example.com/%{HTTP:Accept-Language}/[/URL][red]?nocheck=true[/red] [L, R=301]

you would need to add rules that check for the existence of the nocheck and take action accordingly.

this is a possible way only. I do not recommend it. since you are using a server side language like php it is significantly better to deliver content dynamically through php and not rely on server specific extensions.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top