views:

71

answers:

3

Hi

I've tried dozens of different ways of doing this but can't get any of them to work. My .htaccess does a few things, like setting a custom 404 and blocking image hotlinking. I want to do two things on the URL: add www. if it isn't there (rather annoying Facebook login can't cope with two different sources!), and replacing // with / except after http:.

I've tried this:

# Replace // with /
RewriteCond %{REQUEST_URI}     (.*)(?<!http:)\/{2,5}(.*)
RewriteRule .*                 %1/%2 [R=301,L]

And this:

# Replace // with /
RewriteCond %{REQUEST_URI}     (.*).com\/\/(.*)
RewriteRule .*                 %1.com/%2 [R=301,L]

And all sorts of permutations. Can anybody tell me what I'm doing wrong?

I need to do this because sometimes multiple /s are being inserted between the .com and the rest of the URL.

Thanks

A: 

I don't think http:// is part of REQUEST_URI at all (or of any other environment variable for that matter). It will get parsed out by the browser, and used to determine the nature of the request, long before the actual request is made.

I can be wrong, but I think this is not fixable on htaccess level. The link would have to be properly formatted in the first place.

Update: Looking at the information Apache passes on to PHP, I think I'm right. The protocol used to make the request is not part of the URI components we get to play with.

Pekka
Thanks for the reply. Just to be clear, I'm trying to change example.com//page.php to example.com/page.php. Surely that should be possible?
John Jameson
@John Jameson - When `mod_rewrite` receives the request, any multiple slashes have already been converted to a single slash, e.g. a request to `example.com//a///b` becomes `a/b` as input to a `RewriteRule`.
Tim Stone
@John ah, I think I misread you there. What you state is definitely possible, and should be contained in `REQUEST_URI`. I was referring to `http:////` style mistakes, which the browser would have to sort out so it can make the request. However, `REQUEST_URI` doesn't contain the domain name. I think that is your mistake.
Pekka
@Tim But the browser still displays example.com//signin.php and the page doesn't work. If I delete the extra / it works fine. Any ideas? I'm trying to track down why the extra / gets added, but thought that this would be a temporary solution.
John Jameson
@John it will work when you remove the domain name. `REQUEST_URI` starts with the first slash. If your incoming URL is `http://domain.com/////test`, `REQUEST_URI` should contain `/////test`. If you adjust your regex accordingly, it should work. (I'm not enough of a regex Guru to tell you how, or I would)
Pekka
@Pekka I've also tried HTTP_HOST and that doesn't work either. Can you advise what I should be using?
John Jameson
@John `REQUEST_URI` is the thing, it should work with that. I just tested locally and got `//////test.php` as the value for REQUEST_URI so this is what you need to use. I'm off for today, good luck!
Pekka
@Pekka Never did get it to work, but I tracked down where the spurious / was coming from and fixed it. Thanks for your help.
John Jameson
+1  A: 

Here's how to force www.:

<IfModule mod_rewrite.c>
#Add WWW
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
#End Add WWW
</IfModule>

Considering what @Tim mentioned below, I would check %{REQUEST_URI} if it contains //, and that would be my RewriteCond:

<IfModule mod_rewrite.c>
#Replace // with /
RewriteCond %{REQUEST_URI} // [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
#End Replace // with /
</IfModule>
aularon
Yes, thanks, I've got that bit working. I only mentioned it in case it explained why the other bit wasn't working.
John Jameson
I edited adding a solution to the second problem.
aularon
A: 

I'm not sure why you're experiencing trouble with the multiple slashes, since it should be able to resolve the file either way. However, it is possible to check for and remove them with a redirect (I've combined this with your force-www so there's at most one external redirection):

RewriteCond %{THE_REQUEST} ^[A-Z]+\s[^\s]*/{2,} [OR]
RewriteCond %{HTTP_HOST}  !^www\.
RewriteCond %{HTTP_HOST}   ^(www\.)?(.*)$
RewriteRule ^ http://www.%2%{REQUEST_URI} [R=301,L]

Note that %{REQUEST_URI} has the duplicate slashes removed (only in mod_rewrite, this isn't true for scripts later on), so we can use it in the redirect to automatically take care of that issue for us. The original request will still have the multiple slashes though, so we check for them by examining %{THE_REQUEST}.

Tim Stone
@tim Thanks for the answer.
John Jameson
@John Jameson - No problem. I saw in the comments to Pekka's answer that you were able to kill off the extra slashes at the source after all, so good job on that.
Tim Stone