homepage Welcome to WebmasterWorld Guest from 54.196.62.132
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / Apache Web Server
Forum Library, Charter, Moderators: Ocean10000 & incrediBILL & phranque

Apache Web Server Forum

    
.htaccess trailing slash question
gcan




msg:4421919
 12:00 pm on Feb 26, 2012 (gmt 0)

I have this rewrite rule in my .htaccess file:

RewriteRule ^group/([^/]+)$ group.php?gid=$1 [L,QSA]

It works without and with trailing slash:

htp://mydomain.com/group/group-name/
htp://mydomain.com/group/group-name


Is it necessary to add or remove trailing slash to avoid 2 versions of the same URL?

If yes, how can I remove trailing slash so tht it doesn't affect other rewrite rules?

 

lucy24




msg:4421923
 12:27 pm on Feb 26, 2012 (gmt 0)

Wait. Back up. The rule specifically says

^group/([^/]+)$

so how can it work with a trailing slash? Is there another rule that you haven't mentioned?

Is this part of a rewrite/redirect package, where the user sees a pretty URL and you serve content from an unpretty location? If so, what's the QSA doing? Seems like there shouldn't be a query string before you do the Rewrite.

Is /group-name/ a real directory? If it is, you also have to watch out for mod_dir involvement.

The trailing slash-- present or absent-- doesn't just present a Duplicate Content issue. It raises a more serious Locations problem, because a slash has meaning.

/group-name/ means you're in a directory-- that is, in its index file. Doesn't matter if the directory really exists or not.
/group-name means you're in a file. Again, doesn't matter if the file really exists.

One or the other. Not both.

gcan




msg:4421925
 12:49 pm on Feb 26, 2012 (gmt 0)

lucy24, thank you for your reply. I am sorry, I was wrong - this rule doesn't work with trailing slash. I looked at another rule.

Anyway, I decided to remove trailing slash if it's not a directory. Now I can not combine the 3 rules below.

First I want to remove trailing slash (if not a directory). Then I want 2 rewrites:
http://mydomain/nickname
http://mydomain/group/group-name


Unfortunately, the rules below doesn't work :(

RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [NC]
RewriteRule ^([a-z0-9-]+)\/?$ profile.php?nick=$1 [QSA,L]
RewriteRule ^group/([^/]+)$ group.php?gid=$1 [L,QSA]

lucy24




msg:4422089
 12:49 am on Feb 27, 2012 (gmt 0)

Before you start redirecting: What do your links currently say? All links from your own site-- and any others that are under your direct control-- should lead directly to what you want the user's browser to display. The redirects are only to pick up outdated links coming in from outside: search engines, bookmarks and so on.

So let's get those sorted out.

#1 What you want the user's address bar to show
#2 What your outdated links currently say
#3 Where the content "really" lives

Nos. 2 and 3 might happen to be the same, but they're not automatically the same. It depends on whether you've been making other changes at the same time.

The form !-d is a last resort for when you can't use anything else to weed out the real directories. Do you have a particular reason for using {SCRIPT_FILENAME} instead of the more common {REQUEST_URI}?

Universal guideline: Leave a blank line after each RewriteRule, and put a #comment before each Rule (or group of closely related rules). This is so that when you look back at the file later, you will know right away what each Rule is for. mod_rewrite is hard enough without having to detour into "I have no idea what I was trying to do here" :)

g1smd




msg:4422090
 12:57 am on Feb 27, 2012 (gmt 0)

Good advice. Remember too that a RewriteCond affects only the single RewriteRule that it precedes.

gcan




msg:4422250
 2:17 pm on Feb 27, 2012 (gmt 0)

OK, here is the problem. I want to make user profiles look like this:

http://www.mydomain.com/username

The only way how can I reach it is: !-d

I also tried this rule:

RewriteRule ^([^/.]+)$ profile.php?nick=$1 [L,QSA]

it works but causes the following problem: if I try to open existing directory:

http://www.mydomain.com/directory_name (without trailing slash)

it rewrites to:
http://www.mydomain.com/directory_name/?nick=directory_name

Can anyone suggest how can I solve this problem?

g1smd




msg:4422255
 2:21 pm on Feb 27, 2012 (gmt 0)

Open folders by using a URL that has a trailing slash.

Investigate the DirectorySlash directive. Does it fix up folder URLs before your rewrite has a chance to operate on the incoming request?

gcan




msg:4422266
 2:54 pm on Feb 27, 2012 (gmt 0)

Do you have a particular reason for using {SCRIPT_FILENAME} instead of the more common {REQUEST_URI}?


If I use
RewriteCond %{REQUEST_URI} !-d, the URL rewrites to http://www.modomain.com/nick even if directory exists.

Open folders by using a URL that has a trailing slash.


Yes, I can do it but I can't tell to do so, for example, to the search engines.

Investigate the DirectorySlash directive. Does it fix up folder URLs before your rewrite has a chance to operate on the incoming request?


I don't use DirectorySlash. As I know it causes other problems and I don't understand how can it help to avoid rewrites like :
http://www.mydomain.com/directory_name/?nick=directory_name

Remember too that a RewriteCond affects only the single RewriteRule that it precedes.


g1smd, does it mean that if I need 2 rules with the same condition, the .htaccess file should look like this?

RewriteCond %{SCRIPT_FILENAME} !-d
First rule
RewriteCond %{SCRIPT_FILENAME} !-d
Second rule

lucy24




msg:4422460
 12:38 am on Feb 28, 2012 (gmt 0)

I don't use DirectorySlash. As I know it causes other problems and I don't understand how can it help to avoid rewrites like : http://www.example.com/directory_name/?nick=directory_name

You don't use DirectorySlash. It uses itself, unless you have explicitly turned it off. Clearly you haven't done so, or you wouldn't have /directory_name turning into /directory_name/ in the first place.

[httpd.apache.org...]

does it mean that if I need 2 rules with the same condition, the .htaccess file should look like this?
<snip>

You can sometimes consolidate similar rules by careful use of pipes. For example

RewriteCond blahblah
RewriteRule (one|two|three)^ newfile.php?var=$1 [L]

Or swap things around so you have a string of [OR] conditions feeding into a single Rule.

gcan




msg:4422566
 9:44 am on Feb 28, 2012 (gmt 0)

You don't use DirectorySlash.


Yes, I mean I have not turned it off. I would not to do so because turning off DirectorySlash may cause security problems.

Or swap things around so you have a string of [OR] conditions feeding into a single Rule.


Yes, I know I can use [OR] to create two conditions but I need to create 2 rules for the same condition:

Rule 1 removes trailing slash if directory doesn't exist
Rule 2 rewrites file if directory doesn't exist. As I understand the only way to achieve it is the following:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z0-9-]+)\/?$ profile.php?nick=$1 [L,QSA]


Ths is very bad - !-d is not the best solution but in this case it being used twice. So, I have to forget about it.

Now I found the following solution:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)$ profile.php?nick=$1 [L,QSA]


It still uses !-d but works correctly:
- it makes rewrite only if directory doesn't exist
- it rewrites only URLs without trailing slash at the end
- it doesn't make unexpected rewrites like
http://www.mydomain.com/directory_name/?nick=directory_name

If somebody knows how is it possible to use this rule so that it doesn't rewrite
http://www.mydomain.com/directory_name
to
http://www.mydomain.com/directory_name/?nick=directory_name
(if directory exists), please let me know.

One more question. Which is correct:

RewriteRule ^([^/.]+)$ profile.php?nick=$1 [L,QSA]
RewriteRule ^([^/.]+)$ /profile.php?nick=$1 [L,QSA]

profile.php or /profile.php ?

g1smd




msg:4422768
 6:58 pm on Feb 28, 2012 (gmt 0)

I prefer to specify a leading slash on the target path.

When the target is /$1-something (with a backrefence at the beginning) omitting the leading slash leaves your site wide open to hackers.

gcan




msg:4422869
 10:36 pm on Feb 28, 2012 (gmt 0)

Thanks.

lucy24




msg:4422875
 10:59 pm on Feb 28, 2012 (gmt 0)

When the target is /$1-something (with a backrefence at the beginning) omitting the leading slash leaves your site wide open to hackers.

I went off to investigate this, because I see it regularly. Clearly I didn't use the right search terms, because I'm morally certain it has been said more than three times over the years ;) I did find this expanded version from 2010:

Beware that a target of $1.php allows the user to inject whatever path information they want. You must use /$1.php with a leading slash to mitigate this security risk.

But that was in a thread where the $1 referred to something in the form [^.]+ so there could be any number of intervening directories. If the original capture is expressed as ^([^./]+)$ haven't you already constrained it to the top level?

g1smd




msg:4422935
 1:36 am on Feb 29, 2012 (gmt 0)

You might have, but why take that risk? I prefer to always use a leading slash, then I don't have to worry about that issue.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Apache Web Server
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved