Mod-rewrite + PHP -- query-string being appended to URL?!

Discuss practical ways rearrange URLs using mod_rewrite.

Mod-rewrite + PHP -- query-string being appended to URL?!

Postby philpem » Fri Jul 18, 2008 7:17 am

Hi,
I'm trying to track down an issue with a set of rewrite rules that I'm using to convert links from www.mysite.com/dir/page (and /dir/page/) format into a query-string for a script. To give a better example:

www.example.com/projects/foo => /index.php?projects/foo
www.example.com/projects/foo/ => /index.php?projects/foo/

However, any file that exists in htdocs overrides the script. So if I had a file called 'photo.jpg' in htdocs/projects/foo and someone requested www.example.com/projects/foo/photo.jpg, Apache would handle it as a file instead of redirecting to the script. This saves me writing more code to handle images, and probably a bit of CPU time as well.

Now, this works great, as long as the URL ends with a forward slash. If this is not the case, then my script sends out a Location: header to redirect it, like Apache does with directories -- if you request the directory /foo, you get a 301 Redirect to /foo/ (which then grabs the index page).

If the URL doesn't end with a forward slash, the URL goes from www.example.com/foo/bar to www.example.com/foo/bar/. This works fine if the directory /htdocs/foo/bar/ doesn't exist. If that directory *does*
exist, then the user gets sent to www.example.com/foo/bar/?foo/bar/ instead of www.example.com/foo/bar/.

These are my rewrite rules, as stored in the .htaccess file:
Code: Select all
RewriteEngine On
RewriteBase /

# Apply to primary hosts only
RewriteCond %{HTTP_HOST} ^philpem.me.uk$ [NC,OR]
RewriteCond %{HTTP_HOST} ^www.philpem.me.uk$ [NC]

# This makes sure AWStats can get through
RewriteCond %{REQUEST_URI} !^/awstats.* [NC]

# Additional rules -- temp dir
RewriteCond %{REQUEST_URI} !^/temp.* [NC]

# Enable the next condition if you want physical files to override the CMS
# (this should normally be on, otherwise images, etc. will be forwarded to the
# CMS, which is generally not what you'd want to happen)
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule ^(.*)$ index.php?$1 [L]


Can anyone see what I'm doing wrong here?

Thanks,
Phil.
philpem
 
Posts: 2
Joined: Fri Jul 18, 2008 5:32 am

Postby richardk » Fri Jul 18, 2008 3:09 pm

Mod_dir runs after mod_rewrite (after the query string has been created) and redirects to add the trailing slash that is missing from the directory request. Try
Code: Select all
Options +FollowSymLinks

RewriteEngine On

# Add missing trailing slashes.
RewriteCond %{SCRIPT_FILENAME}/ -d
RewriteRule [^/]$ %{REQUEST_URI}/ [R=301,L]

RewriteCond %{HTTP_HOST} ^(www\.)?philpem\.me\.uk$ [NC]
RewriteCond %{REQUEST_URI} !^/(awstats|temp)(/.*)?$ [NC]
RewriteCond %{SCIRPT_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?$1 [L]
richardk
 
Posts: 8800
Joined: Wed Dec 21, 2005 7:50 am

Postby philpem » Sat Jul 19, 2008 4:02 pm

richardk wrote:Mod_dir runs after mod_rewrite (after the query string has been created) and redirects to add the trailing slash that is missing from the directory request. Try
Code: Select all
Options +FollowSymLinks

RewriteEngine On

# Add missing trailing slashes.
RewriteCond %{SCRIPT_FILENAME}/ -d
RewriteRule [^/]$ %{REQUEST_URI}/ [R=301,L]

RewriteCond %{HTTP_HOST} ^(www\.)?philpem\.me\.uk$ [NC]
RewriteCond %{REQUEST_URI} !^/(awstats|temp)(/.*)?$ [NC]
RewriteCond %{SCIRPT_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?$1 [L]


That works a treat, after fixing the obvious typo (SCIRPT_FILENAME --> SCRIPT_FILENAME). I've got it running on my "beta" site, and everything seems to be working great.

I'm not quite sure I understand how the first two rules work.. I'll take another look tomorrow and see if I can figure them out.

Thanks!
philpem
 
Posts: 2
Joined: Fri Jul 18, 2008 5:32 am

Postby richardk » Sun Jul 20, 2008 12:28 pm

Code: Select all
RewriteCond %{SCRIPT_FILENAME}/ -d

Is the request to a directory (-d)? %{SCRIPT_FILENAME} is the full server path to the request, the document root and everything.

Code: Select all
[^/]$

The request must not end in a / ([a] matches "a", [^a] matches anything that isn't "a").

Code: Select all
%{REQUEST_URI}/

Is the same path, but with a trailing slash, to redirect to.
richardk
 
Posts: 8800
Joined: Wed Dec 21, 2005 7:50 am


Return to Friendly URLs with Mod_Rewrite

Who is online

Users browsing this forum: No registered users and 101 guests

cron