Adding exceptions to mod_rewrite - apache

I got my basic redirects work with the mod_rewrite module. When requesting pages e.g. localhost/home it's correctly redirecting to localhost/index.php?page=home, but I have a problem with exceptions.
I created a folder api where I store files by category e.g. api/auth/register.php and api/customer/create.php. I tried to make rewrite rule that contains 2 params (in this example auth and customer) so basically it just drops the .php off from the url.
The rule that I made is following
RewriteRule ^api/(.*)/(.*)/?$ api/$1/$2.php [L]
After adding that line to my .htaccess, problems started to occur. For example my .css and .js files started to redirect. So maybe I need to make some exeption for the apis? Have you some other ideas to improve my rewrite rules?
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/(.*)/(.*)/?$ api/$1/$2.php [L] # problems started to occur after adding this line
RewriteRule (.*) index.php?page=$1 [L,QSA]
Thanks in advance.

RewriteCond will affect only the first following RewriteRule so you need the keep them next to your initial Rule, and move the added one above them (with its own conditions).
Also, your /api rule is not strict enough ((.*) will pick anything, including the slashes), which might not matter in you case, but still. I sugest you try with this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/([^/]*)/([^/]*)/?$ api/$1/$2.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?page=$1 [L,QSA]

Related

Apache htaccess for generic pretty URLs

I've been crazy trying to make my .htaccess work, and followed several examples with no success (of course modifying them because they were mostly static).
My problem, is that I need a generic htaccess to redirect to random php files (omiting the php extension), for example:
/xxxxx/ loads /xxxxx.php
/yyyyy/zz loads /yyyyy.php?param=zz
This is what I am trying with not success:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^MYDOMAIN [NC]
RewriteRule ^(.*)$ http://MYDOMAIN/$1 [L,R=301,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*?)/?$ /$1.php [NC,L]
RewriteRule ^(.*?)/?(.+)$ /$1.php?param=$2 [NC,L]
</IfModule>
The problem is that I am getting 500 server error on any request.
If I comment the last rule, then:
/xxxx works correctly
/xxxx/ works correctly
/xxxx/yyyy does not work correctly (it is not rewriting the wanted
parameter).
Any help will be appreciated as I don't really know what is happening here.
P.S. I also tested to put a "stopping" rule in the beginning like:
RewriteRule ^.*\.php.*$ - [L]
And then I can have both rules without a 500 server error, just having a 404 in the parameters case.
You are getting 500 because your last rule is running without any conditions and causing infinite looping.
You can use these rules in your site root .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f
RewriteRule ^([^/]+)/([^/])/?$ $1.php?param=$2 [QSA,L]

htaccess to route all requests through index add add trailing slash

This probably seems like quite a simple question to most of you, but i'm having a real hard time getting my site to route all requests through the index file whilst also enforcing trailing slashes. I've searched high and low and not found an appropriate solution. My .htaccess so far is as follows:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
This is as far as i have managed to get and works apart from it adds the index.php into the url, for example if a user goes to;
www.example.com/about-us
I would like it to route through index and become;
www.example.com/about-us/
However my above htaccess file produces;
www.example.com/index.php/about-us/
Seems so close yet so far, anything i do to the htaccess file to try and remove the index.php just stops it from working entirely. I am aware my solution is far from perfect, it still allows access to directories and files however its the best i've been able to come up with (would ideally like to deny directory listing!)
Any help is greatly appreciated!
The ordering of rules is quite important in these cases. Switch the two rules order, and you should be getting the desired behaviour:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} /+[^.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]

Unwanted result while using .htaccess for 2 rules

I'm working on a web application with PHP.
I'd like to have clean URLs, so I wrote a .htaccess file for it. Everything is ok, but just for 1 rule.
Look at the code below:
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rule No.1
RewriteRule ^(.*)/(.*)/(.*)/?$ index.php?page=$1&id=$2 [NC,N]
# Rule No.2
RewriteRule ^(.*)/?$ index.php?page=$1 [NC,L]
This is my .htaccess file contents.
If I remove the Rule No.1, and the page be something like www.site.com/news, everything works fine. But when I want to navigate to page www.site.com/news/1/sample-text, all CSS, JavaScript, and image files will destroy (I have not access to them anymore).
Although I wrote Rule No.2 in .htaccess file, but anything did not work and the problem is steel alive.
All images, css and javascript paths are similar to ./js/jquery.js format.
Also, I put RewriteBase / in .htaccess file. But ... :(
Please help me.
Rules will be better if they are like this:
# Rule No.1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)/(.*)/?$ index.php?page=$1&id=$2 [L]
# Rule No.2
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ index.php?page=$1 [L]
=> You need to repeat the RewriteCond lines here: they apply only to the RewriteRule which follows.
Notes:
NC flag (case insensitivity) is useless here
the first rule doesn't use $3
([^/]+) would make more sense than (.*)

CodeIgniter index.php removal htaccess causing mis-redirection

I'm using following htaccess rule which is proposed all over internet for removing index.php in codeigniter urls. And there are some of the redirection rules i added above it.
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]
The problem is:
I'm getting some odd http request, which i think is caused by htaccess rules above.
Here are some of them :
https://www.sitename.com/index.php/favicon.ico
which ought to be .com/favicon.ico
https://www.sitename.com/index.php/scripts/jquery.js
which ought to be .com/public/jquery.js
as a side note im using base tag to redirect assets to /public/
strange thing is i couldnt find where the second redirection happens
i tested whole site and javascript & css files load correctly
i handled this redirections by making my controller ignore those requests but a while ago
a strange error happened. which i asked here:
https://stackoverflow.com/questions/11775849/htaccess-didnt-work-until-renaming-and-then-renaming-back
my guess is that, even though i ignore misredirected request, hosting company receives them and probably it was causing some trouble for them which led to the problem i shared in linked question by a maintenance of hosting company.
Anyway, Question is:
How can i make htaccess rule only redirect requests that doesnt have file extension at the end?
You're missing a line before the REQUEST_FILENAME line:
RewriteCond $1 !^(index\.php|assets|something|fav\.ico|robots\.txt)
You can modify this to suit your needs. I've got my JS/CSS etc in the assets folder so it's not affected by the rewrite.
so the full .htaccess will look like this:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond $1 !^(index\.php|assets|something|fav\.ico|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]

RewriteRule not working fine

I wrote the following rule in .htaccess
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)/$ profile.php?business=$1
When i enter the URL like
http://www.abc.com/mujeeb/
page is correctly transfered to profiles page and page looks fine.
But i enter this in URL
http://www.abc.com/mujeeb
page doesn't show.
Can you please tell why? Or write the rule for this? i tried many times but not sucessful.
Mujeeb.
page doesn't show. because you specified that you RewriteRule is applied to the URL's ending with / at the end. Rewrite it as
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
And I hope that you have additional RewriteCond statements in order to prevent the infinite loop with redirects.
ps: basically you can prevent loop in two way
1) checks that requested url does not correspond to the existing file or directory. it is, probably, the best way to do (read comments to the second method)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
2) checks that you are requesting not the file from RewriteRule. This method is not good, because for each request, even for existing files and directories, it calls profile.php script
RewriteCond %{REQUEST_URI} !profile\.php$
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
It is because you check for the trailing slash with ^(.*)/$. If you add a question mark, the trailing slash will be optional.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)/?$ profile.php?business=$1
The RewriteCond is neccessary to make sure the Rule will only be applied once. Otherwise Apache will be caught in an infinite loop.
Try this:
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)[/]?$ profile.php?business=$1
That makes the last slash optional.
Well you rule is checking for a trailing slash in URI and that's the reason /mujeeb/ works but /mujeeb does not. Change your code to:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
# If the request is not for a valid file
#RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid directory
#RewriteCond %{REQUEST_FILENAME} !-f
# your rule without trailing slash
RewriteRule ^(.*)$ profile.php?business=$1 [L,QSA]
Plenty of good answers already. My answer is a bit different.
This is what I usually do. If the requested URL doesn't end with a /, I make the browser redirect to a URL with the trailing /. This is consistent with the default behaviour of Apache (due to mod_dir). So, this is how I solve this problem.
RewriteEngine On
# Canonicalize http://example.com/mujeeb to http://example.com/mujeeb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)([^/])$ /$1$2/ [R=307,L]
# Let profile.php process http://example.com/mujeeb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ profile.php?business=$1