Welcome to WebmasterWorld Guest from 54.196.238.210

Forum Moderators: Ocean10000 & incrediBILL & phranque

Message Too Old, No Replies

.htaccess trailing slash question

     

gcan

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

5+ Year Member



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

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

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



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

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

5+ Year Member



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

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

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



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

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

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



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

gcan

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

5+ Year Member



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

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

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



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

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

5+ Year Member



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

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

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



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

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

5+ Year Member



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

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

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



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

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

5+ Year Member



Thanks.

lucy24

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

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



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

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

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



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.
 

Featured Threads

Hot Threads This Week

Hot Threads This Month