"We need all our URL's to have a trailing slash", was a request I had in recently.
This sounds easy enough, a quick rewrite rule will do the trick, and that is what I added.
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]
This works great for pages already on the server, for example
/guestbook
becomes /guestbook/
. However, what if we wanted to load /logo.gif
, this would rewrite to /logo.gif/
and cause a error. OK, so we need not to match every character in the URL, but only if it doesn't have a dot in there. The site in question was a Zend Framework application, and this caused it's own problems.
Zend Framework applications have their own rewriting rules...
RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L]
So what happens if
/guestbook
is actually a Zend Framework application? Well, the URL would be rewritten to
/index.php/
. Why? Well the first rewrite we added a slash, this caused the page to re-requested, this then passed to the Zend Framework rewrites, this saw it needed to rewrite to index.php, this caused the page to be re-requested again internally, which added a slash to the end, and redirected again. Finally this request was /index.php/ which doesn't exist and failed.
Wow, that was a mouthful, let's look at that as a sequence diagram.
What we need is to only rewrite the requested URL if it doesn't have a trailing slash and if it doesn't have a dot in the request and if it isn't an internal Apache redirect. We also only want to rewrite if the request is a GET, POSTs (DELETE's and PUT's too) don't support rewriting in the browser.
This indicates a series a conditions that need to be met, so tells me we should be using Apache's
RewriteCond
directive. Let's check for a GET request first...
RewriteCond %{REQUEST_METHOD} GET [NC]
%{REQUEST_METHOD}
variable in a rewrite rule tells us the HTTP method used to make the request, so we just need to check if that is GET. The [NC]
makes the check case insensitive so matches GET, get, Get, etc... Next we need to see if the request already has a trailing slash.
RewriteCond %{REQUEST_URI} !/$
Now we need to check if there are any dots in the request.
RewriteCond %{REQUEST_URI} !\.
If all these conditions match, we can issue our RewriteRule.
RewriteRule ^.*$ %{REQUEST_URI}/ [R=301,L]
L
to tell Apache not to process any more rules. Let's put this all together, and insert it above the normal Zend Framework rewrites, but after
RewriteEngine On
. RewriteCond %{REQUEST_METHOD} GET [NC] RewriteCond %{REQUEST_URI} !/$ RewriteCond %{REQUEST_URI} !\. RewriteRule ^.*$ %{REQUEST_URI}/ [R=301,L]
/guestbook
again, and see what happens. courtsy: robertprice dot co dot uk
No comments:
Post a Comment