How can I use mod_rewrite on current directory only? - apache

Currently I have these rules in my .htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*).css style.php?u=$1 [QSA]
RewriteRule ^(.*).xml rss.php?u=$1 [QSA]
</IfModule>
This will rewrite the following URLs:
http://domain.com/user.css
http://domain.com/user.xml
But when I'm trying to grab a file from a subdirectory: http://domain.com/css/style.css it gets rewritten as well.
My goal is rewrite only for current directory and avoid sub-directories, since all real CSS files on sub-directories will be rewritten.
How I can avoid this?

You need to make your pattern more restrictive: this ^(.*).css will match ANYTHING with .css in it while this pattern ^([^/]+)\.css$ will be restricted to something.css (styles\something.css will not match it).
<IfModule mod_rewrite.c>
RewriteEngine On
# do not do anything to real files or folders
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
RewriteRule ^([^/]+)\.css$ style.php?u=$1 [QSA,L]
RewriteRule ^([^/]+)\.xml$ rss.php?u=$1 [QSA,L]
</IfModule>

The easiest way is to tell mod_rewrite to avoid rewriting if the file is a real file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*).css style.php?u=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*).xml rss.php?u=$1 [L,QSA]
I've added a [L] tag (end) because once a rule is applied you certainly doesn't need the next rule to be checked.
Now if the files really exists but you really want to handle them with a php script if no 'css' subdirectory is present on the url... let's try that:
<Location "/css">
RewriteEngine off
</Location>

Related

Mod rewrite to remove subdirectory and file extension without breaking DirectoryIndex

I have all site pages in a subdirectory like this...
http://www.example.com/pages/myfile.php
I want the URL to look like this...
http://www.example.com/myfile
Where both the subdirectory called pages and the .php file extension are removed from the URL.
My latest (partial) attempt...
Options All -Indexes +FollowSymLinks
DirectoryIndex index.php
RewriteEngine On
RewriteBase /
RewriteCond %{DOCUMENT_ROOT}/pages%{REQUEST_URI}\.php -f [OR]
RewriteCond %{DOCUMENT_ROOT}/pages%{REQUEST_URI} -d
RewriteRule ^(.*)$ /pages/$1.php [NC,L]
However, this totally breaks DirectoryIndex. When I go to http://www.example.com/ or http://www.example.com/foo/, I get a 404 error instead of defaulting to index.php as defined by DirectoryIndex.
Apparently, it treats everything as a file name instead of recognizing the lack of a file name (directory) and attempting to use index.php.
I tried incorporating this solution into mine, it fixed the DirectoryIndex issue, but it broke everything else.
Is there a solution? Please include a detailed explanation within your answer so I can learn where/how I was going wrong.
Try this in root .htaccess:
Options All -Indexes +FollowSymLinks
DirectoryIndex index.php
RewriteEngine On
RewriteBase /
# add a trailing slash if pages/<uri> is a directory
RewriteCond %{DOCUMENT_ROOT}/pages/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=302]
RewriteRule ^/?$ pages/index.php [L]
# skip all files and directories from rewrite rules below
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# if corresponding .php file exists in pages/ directory
RewriteCond %{DOCUMENT_ROOT}/pages/$1\.php -f
RewriteRule ^(.+?)/?$ pages/$1.php [L]
# route all requests to pages/
RewriteRule ^((?!pages/).*)$ pages/$1 [L,NC]

Changing url with .htaccess

I have a site like "abc.com/1_en-Application.html . Now i want to change it to abc.com/application.html.
I have .htaccess like
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^([0-9]+)-([0-9]+)_(.*)-(.*).html$ index.php?id=$1&page=$2&lang=$3 [L]
RewriteRule ^([0-9]+)_(.*)-(.*).html$ index.php?id=$1&lang=$2 [L]
</IfModule>
Please help me how can i do this ?
Add the 3 lines below the existing rewrite rules:
RewriteCond %{REQUEST_URI} /application.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^application.html$ index.php?id=1&lang=en [L]
If you don't have a real file called application.html in the web root directory, this will rewrite the URL and internally direct it to index.php
If application.html is a real file, it will be shown instead. In that case, the 3 lines will still work but not necessary to include.

How do I create an .htaccess to serve index if the last node is a directory, else, serve a file?

So, if I have the following URL:
http://www.example.com/Foo/Bar/Drink/
The last node of the URL (in this case, Drink) will be either a directory, in which case I want to serve index.php, or it will be a file named "Drink.php", in which case I want to serve them that file.
http://www.example.com/ would obviously serve index.php.
Both would maintain that "pretty URL" look with the trailing slash.
Is this possible? The site will follow this format consistently and I'm really trying to avoid having to route everything through the main index file.
place this code in .htaccess under the root directory of your site
Options -MultiViews
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) /$1/index.php [QSA,L]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ /$1.php [QSA,L]
I think a rewrite rule might do the trick. Try something like this:
Options +FollowSymLinks
DirectoryIndex index.php
RewriteEngine On
RewriteBase /Foo/Bar/Drink
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /Foo/Bar/Drink HTTP/
RewriteRule ^Drink.php$ http://www.yourdomain.com/Foo/Bar/Drink [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /Foo/Bar/Drink/Drink.php [L]

.htaccess rule - check if the request is for a folder or file?

I need to check the requested URL, and serve different options depending on whether the request is for a file or a directory.
My URLs would look like:
http://www.example.com/Services/Service-1 (directory, serve /pages/Services/Service1/index.php)
http://www.example.com/Services/Service-1/Feature-1/Sub-Feature (an actual file, serve /pages/Services/Service-1/Feature-1/Sub-Feature.php)
Because of my lack of understanding of .htaccess (would this need a RewriteCondition?), I am currently stuck enumerating out each and every folder of my directory structure as follows:
RewriteRule ^Services/Service-1/(.*)$ /pages/Services/Service-1/$1.php
RewriteRule ^Services/Service-1 /pages/Services/Service-1/index.php
RewriteRule ^Services/Service-2/(.*)$ /pages/Services/Service-2/$1.php
RewriteRule ^Services/Service-2 /pages/Services/Service-2/index.php
RewriteRule ^Services/(.*)$ /pages/Services/$1.php
RewriteRule ^Services /pages/Services/index.php
RewriteRule ^Testimonials/(.*)$ /pages/Testimonials/$1.php
RewriteRule ^Testimonials /pages/Testimonials/index.php
Needless to say, this is a real pain - any time I add folders of content, I have to mess with .htaccess.
I know there must be a better way, but my google and stackoverflow searches haven't turned up anything that works when I try it.
you guessed it right, a rewriteCond can be used to verify if the requested uri is a file or a directory:
# f for a file, d for a directory
RewriteCond %{REQUEST_FILENAME} -f
you .htaccess would be:
Options -MultiViews
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) /$1/index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule (.+) /$1.php [QSA,L]
EDIT:
if your files reside in the page sub directory , you have to use the following code:
Options -MultiViews
RewriteEngine ON
RewriteCond %{DOCUMENT_ROOT}/pages/$1 -d
RewriteRule (.+) /pages/$1/index.php [QSA,L]
RewriteCond %{DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule (.+) /pages/$1.php [QSA,L]
By far the easiest if mod negotiation is enabled (it usually is):
Options MultiViews
MultiviewsMatch Any
DirectoryIndex index.php
Won't force the .php though, if you have somefile.html as well as somefile.php the .html file is usually selected.

mod_rewrite: add trailing slash?

I am using a .htaccess file to direct requests for a directory to a custom php file that provides info about that directory (and i want the url displayed by the browser to not change).
Here is the relevant part of the .htaccess file.
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ /myphp.php?url=%{REQUEST_URI} [QSA,L]
This works well if you go to a directory and include a trailing slash:
http://domain.com/path/
But without the trailing slash, it doesn't
http://domain.com/path
The url (shown in the browser) turns into:
http://localhost:8888/path/?url=/path
I've tried fixing this by adding a rule above this rule:
RewriteCond %{REQUEST_FILENAME} -D
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L]
But that isn't working for me.
How can I get .htaccess to add the trailing slash if it is omitted and then act just as if it had been there?
Thank you
Update:
As requested, here is the whole thing.
<IfModule mod_rewrite.c>
RewriteEngine On
#force trailing slashes on real directories
RewriteCond %{REQUEST_FILENAME} -D
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L]
#use the directory viewer on directories without an index page
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ /myphp.php?url=%{REQUEST_URI} [QSA,L]
</IfModule>
This line:
RewriteCond %{REQUEST_FILENAME} -D
Should have been:
RewriteCond %{REQUEST_FILENAME} -d
Don't bother with Mod Rewrite, there is a directive for it
<Location /some/path>
DirectorySlash On
SetHandler some-handler
</Location>
http://httpd.apache.org/docs/2.2/mod/mod_dir.html
Did you mean
RewriteRule ^(.*)$ $1/ [L]
instead?
I don't know about your approach. I would try something like
RewriteRule ^/(\S+)/?$ /myphp.php?url=$1
I've used this for rewriting before and it works:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com
RewriteRule ^(.*)$ http://www.domain.com$1
RewriteRule ^/(\S+)/?$ /myphp.php?url=$1
Note that I didn't include the trailing slash in the first rule.
Also, I would advice you not to rely on .htaccess unless absolutely necessary. This is because the server will check for .htaccess files constantly. Using the httpd.conf file instead means apache will only load conditions and rules once. At least I was adviced to do so because of this.
Try this. It will add trailing slash to directory requests which don't have trailing slash.
<IfModule mod_rewrite.c>
RewriteEngine On
#use the directory viewer on directories without an index page
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*?)/?$ /myphp.php?url=$1/ [QSA,L]
</IfModule>