Forum Moderators: phranque

Message Too Old, No Replies

configuring .htaccess to work in subfolders of localhost

         

Maxwell Evans

8:21 pm on Apr 30, 2011 (gmt 0)

10+ Year Member



Hello
I recently created the following code:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /

# Add slashes to the end of everything, if not present:
RewriteCond %{REQUEST_URI} !\.[^./]+$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://localhost/$1/ [R=301,L]

# Redirect about/ and about/X to about.php?get=X:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^page/$ page.php
RewriteRule ^page/([A-Za-z\+\-]+)/?$ page.php?x=$1
</IfModule>


This works on my live server and at the localhost root.

But as I suppose many people do, I seperate my folders inside the localhost for different projects.
So I have:

localhost
|
|
project1 project2 project3 project4

Then within each project I have all the content, css, images etc. Please let me know if I have not explained this very well.

I have basically tried to adapt my code above so that it works within the folders beneath the localhost.

So the .htaccess file I am using for a project called cms is:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /

# Add slashes to the end of everything, if not present:
RewriteCond %{REQUEST_URI} !\.[^./]+$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://localhost/cms/$1/ [R=301,L]

# Redirect about/ and about/X to about.php?get=X:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^about/$ about.php
RewriteRule ^about/([A-Za-z\+\-]+)/?$ about.php?x=$1
</IfModule>


just by loading

[lcoalhost...] in my browser adds the trailing slash as wanted. But it always returns an object not found error.

I'm quite new to the mod_rewrite and really lost as to why this is the case. When the first code above works... Can anyone help me out please.

g1smd

8:54 pm on Apr 30, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



RewriteCond %{REQUEST_URI} !(.*)/$

should not have the (.*) pattern.
Perhaps try: ([^/.]+) instead of (.*) here.

The Rewrite Conditions testing for -f and -d "exists" will affect only the single RewriteRule that follows. In this case they precede the wrong rule.

RewriteRule ^about/([A-Za-z\+\-]+)/?$ about.php?x=$1

promotes Duplicate Content by allowing URLs both with and without a trailing slash. The [L] flag is missing. The hyphen does not need escaping. Add the [NC] flag, and simplify to [a-z0-9+-] here. Decide whether the canonical URL will have trailing slash or not.

The canonical URL for a folder or the index page of a folder should end in a trailing slash. The canonical URL for a page should not end in a trailing slash. The "-f" and "-d" exists checks massively slow your system down. By using an extensionless scheme without a trailing slash, for pages, you can at least remove the "-f" check.

Add the [L] flag to every rule, and remove the <ifModule> tags.

Once the old code is fixed, we can move on to fixing the new code.

Maxwell Evans

9:40 pm on Apr 30, 2011 (gmt 0)

10+ Year Member



Hi g1smd,

Thanks for your reply. I have applied what you have said to my rules, they now look like this:

RewriteEngine on
RewriteBase /

# Add slashes to the end of everything, if not present:
RewriteCond %{REQUEST_URI} !\.[^./]+$
RewriteCond %{REQUEST_URI} !([^/.]+)/$
RewriteRule ^(.*)$ http://localhost/$1/ [R=301,L]

# Redirect about/ and about/X to about.php?get=X:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^page/$ page.php [L]
RewriteRule ^page/([a-z0-9+-]+)/?$ page.php?x=$1 [NC] [L]


A couple of things I was unsure on.

YOu said that "The Rewrite Conditions testing for -f and -d "exists" will affect only the single RewriteRule that follows. In this case they precede the wrong rule. "

I realise this only affects 'page' currently I was going to eventually turn the rule into
RewriteRule ^(about)|(contact)|(blog)/$ $1.php 

Is that what you meant. I wasnt sure sure how it preceded the wrong rule?

Also you mention duplicate content, but by adding the trailing slash automatically like i am doing, doesn't that stop the chances of duplicate content?

I having read around some of your other posts, can see exactly what your saying here regarding the trailing slash for files and the system load. However I am simply scared to touch it. In case I render it useless...And I have made some fairly decent progress (in an area i'm quite new to and find fairly confusing) in terms of how it looks asthetically at least, but I can tell from your reply there is still lots to do to fix the first code and susequently the second set. But i'm looking forward to trying to conquer this with your guidance.

Thank you

g1smd

11:33 pm on Apr 30, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



[NC] [L]
should be
[NC,L]


+)/?$
should be
+)/$
or
+)$
not using a pattern where both are allowed.

Your -f and -d "exists" Rewrite Conditions, check to see if "/page" is a file or folder. They do not belong on this rule.

RewriteRule ^(about)|(contact)|(blog)/$ $1.php

simplifies to
RewriteRule ^(about|contact|blog)/$ $1.php


Also you mention duplicate content, but by adding the trailing slash automatically like i am doing, doesn't that stop the chances of duplicate content?

It does, BUT you should remove the slash when the URL is for a page.

example.com/folder/
-- the URL for a folder.
example.com/page
-- the extensionless URL for a page.
example.com/object.ext
-- the URL for a stylesheet or for an image.

In this way you can simplify your Rules and you can remove the very slow -f and -d "exists" checks altogether.

Maxwell Evans

10:40 am on May 1, 2011 (gmt 0)

10+ Year Member



Hi

This is where I'm up to with my code.


RewriteEngine on
RewriteBase /

## Add slashes to the end of everything, if not present: ##
RewriteCond %{REQUEST_URI} !\.[^./]+$
RewriteCond %{REQUEST_URI} !([^/.]+)/$
RewriteRule ^(.*)$ http://localhost/$1/ [R=301,L]

## Redirect about/ and about/X to about.php?get=X: ##
##RewriteCond %{SCRIPT_FILENAME} !-d ## remove slow checks ##
##RewriteCond %{SCRIPT_FILENAME} !-f ## remove slow checks ##
RewriteRule ^(about|contact|blog|page)/$ $1.php [L]
RewriteRule ^(about|contact|blog|page)/([a-z0-9+-]+)/$ $1.php?x=$2 [NC,L]


I would guess that:


## Add slashes to the end of everything, if not present: ##
RewriteCond %{REQUEST_URI} !\.[^./]+$
[code]RewriteCond %{REQUEST_URI} !([^/.]+)/$
RewriteRule ^(.*)$ http://localhost/$1/ [R=301,L]


Needs to be adjusted to stop the trailing slashes being added.

My understanding of this line:

RewriteCond %{REQUEST_URI} !\.[^./]+$


is where, doesn't start with a '.' and doesnt match a '/'

and this line as:

RewriteCond %{REQUEST_URI} !([^/.]+)/$


doesnt match a '/' or any charachter and ends with '/'

Are those thoughts right?

I would imagine that from here I need to alter the two REQUEST_URIs and the following Rewrite rule in order to basically remove the .php extension.

Is that right?

On a final note do I need the base rewrite still?

Thanks for your help

lucy24

10:39 pm on May 1, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



RewriteCond %{REQUEST_URI} !([^/.]+)/$
RewriteRule ^(.*)$ {stuff that turns into a link when I Preview}/$1/ [R=301,L]

Yawp. Wouldn't that translate as "capture this part only if it doesn't exist"?

RewriteCond %{REQUEST_URI} !\.[^./]+$

is where, doesn't start with a '.' and doesnt match a '/'

Not quite. It means, the entire request does not end with
dot blahblah
where blahblah is any string of any non-zero length that doesn't contain a dot or slash. (But it can contain other characters such as ? or & or =.)

RewriteCond %{REQUEST_URI} !([^/.]+)/$

doesnt match a '/' or any charachter and ends with '/'

Careful. Inside grouping brackets, . no longer means "any character", it means a literal dot. So this line means "any request that doesn't end in one or more non-dot, non-slash characters followed by a slash".

Is it possible that when you say . (dot), you really mean \w for "word characters", i.e. alphanumerics plus lowline? In the case of www addresses it's formally [a-zA-Z0-9_] but you generally don't need to get that specific.

g1smd

1:37 am on May 2, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Wouldn't that translate as "capture this part only if it doesn't exist"?

Yes, you would have trouble if you tried to use the %1 backreference. However in this application we are not. The parentheses are merely for grouping, and might not be needed at all.

Maxwell Evans

8:25 pm on May 2, 2011 (gmt 0)

10+ Year Member



So am I on the right lines that I need to alter the two REQUEST_URIs and the following Rewrite rule in order to basically remove the .php extension?

If I achieve this, would my rules be "ok"?

[edited by: Maxwell_Evans at 8:38 pm (utc) on May 2, 2011]

g1smd

8:37 pm on May 2, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This code does not "remove the PHP extension". What it does is something completely different.

This code should map an extensionless URL request, after the link is clicked, to an internal PHP file.

It consists of patterns which "test" the incoming URL request, and upon finding a match alter the default internal server path pointer to point to the place inside the server where the content really resides.

Maxwell Evans

8:40 pm on May 2, 2011 (gmt 0)

10+ Year Member



Yes sorry, my statement was incorrect. I shall try to rewrite the requests to map an extionless url and report back.

Thanks, Again