How Apache mod_rewrite Module works? - apache

I'm trying to make my own MVC PHP framework using a tutorial that i found over the net .
but i got a problem understanding the rewrite_mod in the htaccess files. here is the first part :
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
</IfModule>
1) As written in the tutorial those rules will redirect all the request to the public folder , so the first question is why we have two rules ? what means the first and the second. one
2) the second part is another htaccess file in the public folder containing :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>
the second part will rewrite the url to index.php?url=$1 this part is clear but this part is little bit difficult for me
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
i learn about it and it tell that the request should not be a file or directory but the index.php is a file (in public directory) .
anothe question please why when we remove the last .htaccess file (in public directory) we
got this error :
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator at admin#127.0.0.1 to inform them of the time this error occurred, and the actions you performed just before this error.
More information about this error may be available in the server error log.
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
and when we have only a htacces containting only this part ,it works great ?
<IfModule mod_rewrite.c>
RewriteEngine On
</IfModule>
Thanks so much .

You can combine and fix the root .htaccess:
RewriteEngine on
RewriteRule !^public/ public%{REQUEST_URI} [L]
This means forward to /public/<uri> if REQUEST_URI does not start with /public
Some explanation now.
DOCUMENT_ROOT/.htaccess:
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
1st rule is internally forwarding to public/ with request URI is empty i.e. http://site.com/
2nd rule is internally forwarding even URI to public/<URI>
DOCUMENT_ROOT/public/.htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
Here inside public direcotry:
RewriteCond %{REQUEST_FILENAME} !-f means if request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-d means if request is not for a valid directory
RewriteRule ^(.*)$ index.php?url=$1 means forward request to index.php?url=<uri>
Reference: Apache mod_rewrite Introduction

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]

how to rewrite URL using .htaccess file?

I am having problem in rewriting a url using .htaccess file. I am not aware of regex. I have red so many blogs and used online rewrite rule generator to generate url and pasted in .htaccess file. But no one is worked. I have enabled mod_rewrite module in httpd.conf file in apache server.
I want to rewrite a below url.
I have developed project in OS - Win7 with Apache server.
http://localhost:81/quora/tamilnanban/innerpage.php?url=why-you-should-avoid-watching-porn-on-android-smartphones
to
http://localhost:81/quora/tamilnanban/why-you-should-avoid-watching-porn-on-android-smartphones
my current .htaccess file contains below codes:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*$ ./index.php
#RewriteRule ^url/([^/]*)\.html$ :81/quora/tamilnanban/innerpage.php?url=$1 [L]
RewriteRule ^/quora/tamilnanban/([^/]*)\.html$ /quora/tamilnanban/innerpage.php?url=$1 [L]
This above rule also not working. Kindly help me to achieve url rewriting using .htaccess file. Also if i am doing any mistakes in the above steps, please correct me. Thanks in advance.
To convert /quora/tamilnanban/innerpage\.php\?url=foobar" to /quora/tamilnanban/foobar you can use the following rules in /quora/tamilnanban/.htaccess :
RewriteEngine on
#1)Redirect "/quora/tamilnanban/innerpage\.php\?url=foobar" to "/quora/tamilnanban/foobar"#
RewriteCond %{THE_REQUEST} /quora/tamilnanban/innerpage\.php\?url=(.+)\sHTTP [NC]
RewriteRule ^ /quora/tamilnanban/%1? [L,R]
#2)The rule bellow will internally map "/quora/tamilnanban/foobar"" to "/quora/tamilnanban/innerpage\.php?url=foobar"#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?(.+)$ /quora/tamilnanban/innerpage\.php?url=$1 [L]

htaccess and URL friendly

I'm trying to make a backend for a site to work with URL friendly. What I'm trying to accomplish is that everything after http://account_name/backend will be redirected to index.php (and that file will take care of the querystring), but if a user is not logged in, index.php will redirect to login and that URL should point to a login.php file.
At this point if I hit http://account_name/backend, I'm being redirected to http://account_name/backend/login and I see the login.php file, but the js and css recources are not loaded. This resources are beeing called like:
<script type="text/javascript" src="js/jquery.js"></script>
Obviously I'm having some path issues, but I can't figure it out. I've tried setting RewriteBase in htaccess and base href in HTML but with no luck.
Also, I should mention that if try to access a js directly I'm being redirected to
http://account_name/backend/js/jquery.js > http://account_name/backend/js/login
The files for the front are in:
D:\FolderA\FolderB\AccountName\Project
The files for the backend are in:
D:\FolderA\FolderB\AccountName\Project\backend
This is my virtual host:
<VirtualHost account_name>
DocumentRoot "D:\FolderA\FolderB\AccountName\Project"
<Directory "FolderA">
AllowOverride All
</Directory>
</VirtualHost>
This is my .htaccess so far:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{ENV:REDIRECT_STATUS} !^[\s/]*$
RewriteRule ^ - [L]
RewriteRule ^login$ login.php [L]
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
Update the last rule to recheck file existence:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
Actually problem is your your first rule that is doing ANDing rather ORing
# if request is for a directory AND
RewriteCond %{REQUEST_FILENAME} !-d
# if request is for a file AND
RewriteCond %{REQUEST_FILENAME} !-f
# if request has been rewritten once
RewriteCond %{ENV:REDIRECT_STATUS} !^[\s/]*$
RewriteRule ^ - [L]
Obviously this rule will never succeed as one request cannot be for a file and and a directory at the same time that has already been rewritten (%{ENV:REDIRECT_STATUS} check).
Due to this rule failing your rule is actually looping and being rewritten like this:
backend/js/jquery.js => index.php?route=backend/js/jquery.js
index.php?route=backend/js/jquery.js => index.php?route=index.php
After step 2 mod_rewrite stops as source and target are same i.e. index.php.
Code inside your index.php then redirects to login as you mentioned in your comment above.
To prevent this behavior you can use rule as suggested by #hjpotter92 above or fix your first rule by using OR between conditions:
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{ENV:REDIRECT_STATUS} !^$
RewriteRule ^ - [L]

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]

htaccess remove index.php from url

I have a problem whereby google has indexed some pages with the wrong url.
The url they are indexing is:
http://www.example.com/index.php/section1/section2
I need it to redirect to:
http://www.example.com/section1/section2
.htaccess isn't my forte, so any help would be much appreciated.
The original answer is actually correct, but lacks explanation. I would like to add some explanations and modifications.
I suggest reading this short introduction https://httpd.apache.org/docs/2.4/rewrite/intro.html (15mins) and reference these 2 pages while reading.
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
https://httpd.apache.org/docs/2.4/rewrite/flags.html
This is the basic rule to hide index.php from the URL. Put this in your root .htaccess file.
mod_rewrite must be enabled with PHP and this will work for the PHP version higher than 5.2.6.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php/$1 [L]
Think %{REQUEST_FILENAME} as the the path after host.
E.g. https://www.example.com/index.html, %{REQUEST_FILENAME} is /index.html
So the last 3 lines means, if it's not a regular file !-f and not a directory !-d, then do the RewriteRule.
As for RewriteRule formats:
So RewriteRule (.*) /index.php/$1 [L] means, if the 2 RewriteCond are satisfied, it (.*) would match everything after the hostname. . matches any single character , .* matches any characters and (.*) makes this a variables can be references with $1, then replace with /index.php/$1. The final effect is to add a preceding index.php to the whole URL path.
E.g. for https://www.example.com/hello, it would produce, https://www.example.com/index.php/hello internally.
Another key problem is that this indeed solve the question. Internally, (I guess) it always need https://www.example.com/index.php/hello, but with rewriting, you could visit the site without index.php, apache adds that for you internally.
Btw, making an extra .htaccess file is not very recommended by the Apache doc.
Rewriting is typically configured in the main server configuration
setting (outside any <Directory> section) or inside <VirtualHost>
containers. This is the easiest way to do rewriting and is recommended
To remove index.php from the URL, and to redirect the visitor to the non-index.php version of the page:
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
This will cleanly redirect /index.php/myblog to simply /myblog.
Using a 301 redirect will preserve Google search engine rankings.
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^ /%1 [R=301,L]
Assuming the existent url is
http://example.com/index.php/foo/bar
and we want to convert it into
http://example.com/foo/bar
You can use the following rule :
RewriteEngine on
#1) redirect the client from "/index.php/foo/bar" to "/foo/bar"
RewriteCond %{THE_REQUEST} /index\.php/(.+)\sHTTP [NC]
RewriteRule ^ /%1 [NE,L,R]
#2)internally map "/foo/bar" to "/index.php/foo/bar"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php/$1 [L]
In the spep #1 we first match against the request string and capture everything after the /index.php/ and the captured value is saved in %1 var. We then send the browser to a new url.
The #2 processes the request internally. When the browser arrives at /foo/bar , #2rule rewrites the new url to the orignal location.
Steps to remove index.php from url for your wordpress website.
Check you should have mod_rewrite enabled at your server.
To check whether it's enabled or not - Create 1 file phpinfo.php at your root folder with below command.
<?php
phpinfo?();
?>
Now run this file - www.yoursite.com/phpinfo.php and it will show mod_rewrite at Load modules section.
If not enabled then perform below commands at your terminal.
sudo a2enmod rewrite
sudo service apache2 restart
Make sure your .htaccess is existing in your WordPress root folder, if not create one .htaccess file
Paste this code at your .htaccess file :-
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Further make permission of .htaccess to 666 so that it become writable and now you can do changes in your wordpress permalinks.
Now go to Settings -> permalinks -> and change to your needed url format.
Remove this code /index.php/%year%/%monthnum%/%day%/%postname%/
and insert this code on Custom Structure: /%postname%/
If still not succeeded then check your hosting, mine was digitalocean server, so I cleared it myself
Edited the file /etc/apache2/sites-enabled/000-default.conf
Added this line after DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
</Directory>
Restart your apache server
Note: /var/www/html will be your document root
Do the following steps
1. Make sure that the hosting / your pc mod_rewrite module is active. if not active then try to activate in a way, open the httpd.conf file. You can check this in the phpinfo.php to find out.
change this setting :
#LoadModule rewrite_module modules/mod_rewrite.so
to be and restart wamp
LoadModule rewrite_module modules/mod_rewrite.so
2. Then go to .htaccess file, and try to modify to be:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]
if above does not work try with this:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
3. Move .htaccess file to root directory, where is index.php there.
www OR root folder
- index.php
- .htaccess
Some may get a 403 with the method listed above using mod_rewrite. Another solution to rewite index.php out is as follows:
<IfModule mod_rewrite.c>
RewriteEngine On
# Put your installation directory here:
RewriteBase /
# Do not enable rewriting for files or directories that exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
I have used many codes from the above mentioned sections for removing index.php form the base url. But it was not working from my end. So, you can use this code which I have used and its working properly.
If you really need to remove index.php from the base URL then just put this code in your htaccess.
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
This will work, use the following code in .htaccess file
RewriteEngine On
# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
I don't have to many bulky code to give out just a little snippet solved the issue for me.
i have https://example.com/entitlements/index.php rather i want anyone that types it to get error on request event if you type https://example.com/entitlements/index
you will still get error since there's this word "index" is contained there will always be an error thrown back though the content of index.php will still be displayed properly
cletus post on "https://stackoverflow.com/a/1055655/12192635" which
solved it
Edit your .htaccess file with the below
to redirect people visiting https://example.com/entitlements/index.php to 404 page
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
to redirect people visiting https://example.com/entitlements/index to 404 page
RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
Not withstanding we have already known that the above code works with already existing codes on stack see where i applied the code above just below the all codes at it end.
# The following will allow you to use URLs such as the following:
#
# example.com/anything
# example.com/anything/
#
# Which will actually serve files such as the following:
#
# example.com/anything.html
# example.com/anything.php
#
# But *only if they exist*, otherwise it will report the usual 404 error.
Options +FollowSymLinks
RewriteEngine On
# Remove trailing slashes.
# e.g. example.com/foo/ will redirect to example.com/foo
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=permanent,QSA]
# Redirect to HTML if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [L,QSA]
# Redirect to PHP if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
try this, it work for me
<IfModule mod_rewrite.c>
# Enable Rewrite Engine
# ------------------------------
RewriteEngine On
RewriteBase /
# Redirect index.php Requests
# ------------------------------
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{THE_REQUEST} !/system/.*
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,L]
# Standard ExpressionEngine Rewrite
# ------------------------------
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
For more detail
create .htaccess file on project root directory and put below code for remove index.php
RewriteEngine on
RewriteCond $1 !^(index.php|resources|robots.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]