Forum Moderators: phranque

Message Too Old, No Replies

Adding trailing slash to directories

With existing rewrite rules

         

davec

11:31 am on Dec 9, 2005 (gmt 0)

10+ Year Member



Hi

I'm running a CMS that rewrites all urls from the following format:

[domain.com...]
[domain.com...]

to:

[domain.com...]
[domain.com...]

I've just noticed that in yahoo search results, although the urls appear correctly in the list it's actually sending people to the url without the trailing slash. I didn't think this would be a problem as I assumed the persons browser would append a trailing slash on the end, but unfortunately all you get is a page not found.

So [domain.com...] works but [domain.com...] (without the trailing slash) gives a page not found.

I've been looking for a way to add a trailing slash if one doesn't already exist, but had no success as it seems to break the existing rules. The current .htaccess file rules are pretty simple, I've included them below. any help on how to get around this problem would be much appreciated.

Kind Regards
Dave

RewriteEngine On

RewriteRule ^admin$ - [L]
RewriteRule ^admin/.*$ - [L]
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteCond %{REQUEST_FILENAME}!-l
RewriteRule (\.html¦/)$ index.php

jdMorgan

3:08 pm on Dec 9, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Try:

RewriteEngine on
#
# Skip remaining rules if request is for "admin<anything>"
RewriteRule ^admin/? - [L]
#
# append "/" if requested URI contains no filetype and does not end in "/"
RewriteCond %{REQUEST_URI} !(\.¦/$)
RewriteRule (.+) http://www.example.com/$1/ [R=301,L]
#
# if requested URI does not exist as a file
RewriteCond %{REQUEST_FILENAME} !-f
# and if requested URI does not exist as a directory
RewriteCond %{REQUEST_FILENAME} !-d
# and if requested URI does not exist as a *nix symbolic link
RewriteCond %{REQUEST_FILENAME} !-l
# then rewrite <anything>.html or <anything>/ to index.php and stop processing rules for this pass
RewriteRule (\.html¦/)$ index.php [L]

Replace all broken pipe "¦" characters above with solid pipe characters before use; Posting on this board modifies them.

Jim

davec

5:02 pm on Dec 9, 2005 (gmt 0)

10+ Year Member



Hi Jim

Thanks ever so much, that works a treat. Time to go and do some more reading on regular expressions.

Cheers
Dave

Patrick Taylor

1:54 pm on Dec 12, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I found this helpful as well. I have been wanting to do the same thing. I have used:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain-name\.com [NC]
RewriteRule ^(.*)$ [domain-name.com...] [R=301,L]

# From ht*p://www.webmasterworld.com/forum92/5117.htm
# Append "/" if requested URI contains no filetype and does not end in "/"
RewriteCond %{REQUEST_URI}!(\.¦/$)
RewriteRule (.+) [domain-name.com...] [R=301,L]

# Rewrite string-string/ as string-string.php
RewriteRule ^([a-z0-9-]+)/$ /$1.php [L]

On one site the code above seems to work perfectly, and on another, for /page the result is /page.php/ - for some reason .php is slipping in. Is there any reason why two different servers would behave differently or have I made an error?

jdMorgan

3:20 pm on Dec 12, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Patrick,

If you work through the logic of the last two rules you posted, you'll see that /page get externally redirected by the second rule to /page/, and then when that request for /page/ arrives at your server, the third rule will add ".php" to it.

So this code is not compatible with your no-filetype-extension naming schema. If you only have a few such problem URLs, you could add execeptions (adding RewriteConds) to the rules so they won't be rewritten. However, if many of your pages are published without filetypes, then you'll have to do a check for "exists as file" before adding the slash and/or ".php" extension. While this serves the same purpose as a check for no "." or trailing "/" in the filename, it is much, much slower -- the server actually has to check to be sure that no file of that name exists on disk.

File exists checks are done with


RewriteCond %{REQUEST_FILENAME} -f

if you want to try that or use it as a key to look for other examples posted here.

Jim

Patrick Taylor

5:02 pm on Dec 12, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Does this not check for a file? >>

# Append "/" if requested URI contains no filetype and does not end in "/"
RewriteCond %{REQUEST_URI}!(\.¦/$)
RewriteRule (.+) [domain-name.com...] [R=301,L]

I can see why the RewriteCond is checking whether there is no trailing slash (and adds one if there isn't one) but I don't understand why there's a need to check for a filetype, as I don't want to show any filetypes.

Confuzzled...

jdMorgan

5:30 pm on Dec 12, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



No that doesn't check for a file, it checks whether the requested URL contains a period or a trailing slash, just as the comment says. On a server where filetypes are used, the check for a period is analogous to a check for a file, and much faster than checking the server's filesystem, but you can't use this expedient if you don't use filetype extensions on your server.

Again, take the /page URL example you posted, and analyze what the code you posted will do with it. The result will clearly be /page.php/

Jim

varunkrish

6:41 pm on Dec 14, 2005 (gmt 0)

10+ Year Member



your greate morgan..worked like charm to me

mealybar

10:41 pm on Dec 14, 2005 (gmt 0)

10+ Year Member



I've been having a trailing slash problem too, cant seem to get the soloutions already posted to fit. The rule I'm now trying is:

RewriteRule ^(.*)$ /temp/indpage.php?id=$1 [R]

URLs sometimes come in on [domain.com...] which only works if there is a trailing slash.

With my rule I would like anything after the ...ain.com/temp/<here> to be passed to temp/indpage.php?id=<here>

Maybe there is a conflict with my other rules so I'll post them below:

My htaccess =>

Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteRule ^(admin¦fld1¦fld2)/ - [L]
>>Above>>RewriteRule ^(.*)$ /temp/indpage.php?id=$1 [R]
RewriteRule ^([^/]+)/(index\.php)?$ /temp/indpage.php?id=$1 [L]
RewriteRule ^([^/]+)/news\.php(.*)$ /temp/newspage.php?id=$1$2 [L]
RewriteRule ^([^/]+)/photo\.php(.*)$ /temp/photopage.php?id=$1$2 [L]
RewriteRule ^([^/]+)/result\.php$ /temo/resultpage.php?id=$1 [L]
RewriteRule ^([^/]+)/result([0-9]+)?\.html$ /temp/resultpage.php?id=$1&rid=$2 [L]

jdMorgan

11:16 pm on Dec 14, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Your rule will externally redirect, not internally rewrite, *all* page requests to /temp/indpage.php?id=$1 and as a result, the changed URL will be visible to your visitors. I doubt that's what you want.

I think you'd serve yourself well by reading the mod_rewrite documentation, the URL Rewriting Guide, and the regular expressions tutorial cited in our forum charter [webmasterworld.com]. Otherwise, you're going to have to keep asking questions until someone gets lucky and guesses right... Not a very efficient use of our time or yours.

That said, I'll take my 'guess' now...

If you need to rewrite additional subdirectories below '/temp' then you'll need two rules:


RewriteRule ^temp/(.+)/$ /temp/indpage.php?id=$1 [L]
RewriteRule ^temp/(.+)$ /temp/indpage.php?id=$1 [L]

If there are no additional subdirectories below 'temp', then one rule will suffice:

RewriteRule ^temp/([^/]+)/?$ /temp/indpage.php?id=$1 [L]

With this rule (or these two rules) in place, *none* of the rules that follow will apply to any URLs in the /temp directory-path. If that's not what you want, then don't use these rules.

Jim

mealybar

11:54 pm on Dec 14, 2005 (gmt 0)

10+ Year Member



Sorry my mistake with the [R], must have left it in from another try.

I'll try and explain again better what isnt/is working.

First my htaccess file is in the domain.com/temp/ folder which is why the other rules are as they are.
A url would be domain.com/temp/<variable> without the trailing slash, which produces a 404. domain.com/temp/<variable>/ with the slash is rewritten to a page which looks that user up in the database to provide certain pages ..com/<variable>/news.php ..com/<variable>/result.php which are rewritten in the other rules to go to one physical page, variable being in the query string.
There are also a few hard directories in the temp/ folder which need to be accessed directly hence the first rule barring a list of folders from being rewritten in the same way as above.

I tried:

RewriteRule ^(.*)$ /temp/indpage.php?id=$1 [L]

but realised that this will place everything after the temp/ folder onto the querystring and never get to access another of the later rules.

What I cant figure out (having read the apache documentation most of the last 4 hours) is to rewrite a url domain.com/temp/<variable> to one with a trailing slash; while conforming to the other rules.

The direction I'm on at the moment is conditions, as <variable> will not contain '.' or '/', so if a url comes in without a slash and without a filetype (unless its going to one of the hard dirs) it will get the trailing slash added. Maybe I'm barking up the wrong tree.

jdMorgan

1:23 am on Dec 15, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




# Add trailing slash if no slash or period in non-blank path below /temp/
RewriteRule ^temp/([^./]+)$ /temp/$1/ [L]

Jim

mealybar

2:44 am on Dec 15, 2005 (gmt 0)

10+ Year Member



Thanks, that did the trick :)