Forum Moderators: phranque

Message Too Old, No Replies

mod rewrite doing strange things

         

johnporter

7:33 pm on Feb 3, 2010 (gmt 0)

10+ Year Member



My mod_rewrite rules are doing strange things in browser that I can't explain or understand. I have the following:

RewriteEngine On
RewriteBase /

RewriteRule^([a-z0-9-]+)/?([a-z0-9-]+)?/?([a-z0-9-]+)?/?$ index.php?x=$1&y=$2&z=$3 [L]

When I type the urls with trailing slashes everything works as it should. When I type urls without the trailing slash, the entire query string is appended to the url including the slash I missed off, like so...


/projects/?x=projects&y=&z=
/projects/test/?x=projects&y=test&z=
/projects/test/again/?x=projects&y=test&z=again


Does anyone know how to stop it from doing this? Maybe I have written the last rule wrong or something, it's really stumped me...

jdMorgan

12:13 am on Feb 4, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, you've missed a step -- you need to detect missing trailing slashes and redirect to add them before mod_dir gets ahold of this request and does it for you, with side-effects as noted.

Options +FollowSymLinks -MultiViews
RewriteEngine on
#
# Externally redirect to add missing trailing slash to search-friendly URLs
RewriteRule ^([a-z0-9\-](/[a-z0-9\-]){0,2})$ http://www.example.com/$1/ [R=301,L]
#
# Internally rewrite search-friendly URLs to script
RewriteRule ^([a-z0-9\-]+)/(([a-z0-9\-]+)/(([a-z0-9\-]+)/)?)?$ index.php?x=$1&y=$3&z=$5 [L]

Jim

johnporter

7:21 pm on Feb 4, 2010 (gmt 0)

10+ Year Member



Thanks for your reply, I knew it would be something as simple as adding a trailling slash with a rule.

However it isn't working like that, it still appends the querystring to the url.

Here is my entire .htaccess file:

Options +FollowSymLinks -MultiViews
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Change www. requests to plain requests
RewriteCond%{http_host} ^www\.example\.com [NC]
RewriteRule^(.*)$ http://example.com/$1 [R=301,NC]

# Image hotlink prevention
RewriteCond%{HTTP_REFERER} !^$
RewriteCond%{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteRule\.(jpg|jpeg|png|gif)$ http://example.com/hotlink.gif [NC,R,L]

# Shorten js and css packers
RewriteRule^js/?$ /application/packers/jspacker.php [L]
RewriteRule^css/ie(\d{1})$ /application/packers/csspacker.php?ie=$1 [L]
RewriteRule^css/?$ /application/packers/csspacker.php [L]

# Externally redirect to add missing trailing slash to search-friendly URLs
RewriteRule ^([a-z0-9\-](/[a-z0-9\-]){0,2})$ http://example.com/$1/ [R=301,L]
#
# Internally rewrite search-friendly URLs to script
RewriteRule ^([a-z0-9\-]+)/(([a-z0-9\-]+)/(([a-z0-9\-]+)/)?)?$ index.php?x=$1&y=$3&z=$5 [L]
</IfModule>

[edited by: jdMorgan at 10:14 pm (utc) on Feb 4, 2010]
[edit reason] example.com [/edit]

jdMorgan

10:17 pm on Feb 4, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You have your rules in the wrong order.

Put all of your access control rules (e.g. hotlink prevention) first, followed by all of your external redirects, followed by all of your internal rewrites. Within each of these three groups, put the most-specific rules first, and the least-specific rules last.

For example, a rule redirecting only a single URL is "most-specific" and a rule redirecting all URLs requested from non-canonical hostnames is least-specific.

Using this method prevents unexpected operation such as multiple chained redirects when both the URL-path and the requested hostname are incorrect, and prevents 'exposing' your internally-rewritten filepaths to clients as URLs, as is the case here.

Once you get your rules in the proper order and confirm that that fixes your problem, we can work on optimizing the code a bit...

Please note that "example.com" is the only domain generally allowed in posts here.

Jim

johnporter

10:47 pm on Feb 4, 2010 (gmt 0)

10+ Year Member



Thanks! Would you be able to explain the order for me, I wouldn't know which ones go where, I just added them as I found on the internet and tried my url rewrites...

Thanks again!

jdMorgan

2:42 am on Feb 5, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




Options +FollowSymLinks -MultiViews
#
RewriteEngine on
#
# Externally redirect hotlinked image requests to replacement image
RewriteCond %{HTTP_REFERER} !^(https?://(www\.)?example.com)?$
RewriteCond %{REQUEST_URI} !^/no-hotlinking\.gif$
RewriteRule \.(jpe?g|gif|png)$ http://example.com/no-hotlinking.gif [NC,R=302,L]
#
# Externally redirect to add missing trailing slash to search-friendly URLs
RewriteRule ^([a-z0-9\-]+(/[a-z0-9\-]+){0,2})$ http://example.com/$1/ [R=301,L]
#
# Externally redirect all requests for non-canonical hostname to canonical hostname
RewriteCond %{HTTP_HOST} !^(example\.com)?$
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
# Internally rewrite search-friendly URLs to script
RewriteRule ^([a-z0-9\-]+)/(([a-z0-9\-]+)/(([a-z0-9\-]+)/)?)?$ index.php?x=$1&y=$3&z=$5 [L]
#
# Internally rewrite short js and css packer URL requests to actual filepaths
RewriteRule ^js/?$ /application/packers/jspacker.php [L]
RewriteRule ^css/ie([0-9])/?$ /application/packers/csspacker.php?ie=$1 [L]
RewriteRule ^css/?$ /application/packers/csspacker.php [L]

Removed <IfModule> container to prevent completely-silent failure if mod_rewrite is unavailable.

Removed unnecessary default-value RewriteBase directive.

Rules placed in correct order: Access control, external redirects, internal rewrites -- all most- to least-specific

Anti-hotlinking rule corrected to allow on-site hosting of hotlinked-image replacement image without causing a loop. Rule subpatterns re-ordered and optimized.

Domain canonicalization rule optimized and now tests for and corrects *all* non-canonical hostnames.

'Packer' rules made more consistent and more portable among server versions.

Improved accuracy of comments.

Jim

[edit] Corrections as noted below. [/edit]

[edited by: jdMorgan at 3:52 pm (utc) on Feb 5, 2010]

johnporter

12:23 pm on Feb 5, 2010 (gmt 0)

10+ Year Member



Thanks for doing that...

My local machine is doing the same error. I have put it on my live hosting server and am getting a 500 internal server error. I have changed the paths to reflect the right domain.

This is really bugging me now and I'm out of my depth with this...

jdMorgan

3:50 pm on Feb 5, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



What's in your server error log file when you get the 500-Server error?

[added] Note that I made a correction to the second rule in my post above. I had forgotten to put "+" quantifiers on two of the inner sub-patterns. Unfortunately, this correction is not likely to effect your server error problem. [/added]

Jim

johnporter

5:50 pm on Feb 5, 2010 (gmt 0)

10+ Year Member



I've had to take the options string out the top, options not allowed on fasthosts servers!

The rewrite rules are working on my live server. Great! Is there any reason why this wouldn't work locally? I use MAMP PRO... Not that I should be asking you these questions ;)

Do you know of any values in Apache setup/PHP setup that would cause the problems I've been having? I imagine it would be Apache somewhere...

Thanks for all your help on this, if I could, I'd buy you a digital pint of beer...

jdMorgan

2:18 am on Feb 6, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, Options may be required on your local server, due to differences in the server-config-level code.

It all depends on what you mean by "it doesn't work," which as you might appreciate, has no useful meaning...

Jim