EllisLab text mark
Advanced Search
     
Better super .htaccess file and tutorial coming your way.
Posted: 19 April 2009 01:01 AM
Avatar
Joined: 2008-05-09
234 posts

It seems that many people are still having .htaccess issues, even as often as it is discussed on these forums.  Looking at all the different posts, it seems that while one answer may resolve one person’s issue, it may not address another person’s issue.

Perhaps it’s time to revisit the super .htaccess file once again that Xeoncross once submitted in these forums, but this time configure that .htaccess file to handle everyone’s issue.  It should be WAY over commented to make sure it is self-explanatory to even the most novice .htaccess users.

Most of us know, what works with most hosts does not work with GoDaddy accounts, and what works with GoDaddy may not work with BlueHost, and BlueHost may not work with DreamHost, etc.  So, an .htaccess where you choose the lines you need is called for, along with explanations on how to choose and why.  I encourage people to respond and help me fine tune the “comments” and the “code lines” until this is the perfect do-all and be-all for all hosting environments.  Once completed and vetted thoroughly, I’ll write up a tutorial that we can all link to when we need to guide newcomers, and it may even be handy for the seasoned people to refer back to once in a while.

Ok, here is the .htaccess file I have so far.  Please feel free to comment/criticize/suggest additions/suggest removals.  If you have a comment or suggestion, please be clear as to why you feel something should be changed, added, removed, along with a simple explanation that those who are novices can understand.

I’ll have to break it up into multiple posts, as it is too long for one post.

#-------------------------------------------------------------------------------
#       CodeIgniter .htaccess file for the main index.php directory
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# If you must have your CI "system" directory at http://www.domain.tld/system/,
# Then I advise you to place a .htaccess file in that directory
# with "deny from all" in it.
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Be sure to replace "domain.tld" with your actual domain and tld anywhere this
# appears in this file.
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Restore "allow from all" / I use a "deny from all" in some directory
# structures, especially where I am hosting multiple sub-domains that point to
# subdirectories of the main domain, this restores it.
#-------------------------------------------------------------------------------
#allow from all

#-------------------------------------------------------------------------------
# Turn off directory listings for increased security
#-------------------------------------------------------------------------------
Options -Indexes

#-------------------------------------------------------------------------------
# Turn on following symbolic links.
#-------------------------------------------------------------------------------
Options +FollowSymLinks

#-------------------------------------------------------------------------------
# Some web servers require this for index.php to be removed properly.  You may
# try your .htaccess with or without the following line.
# Most work fine with it.
#-------------------------------------------------------------------------------
Options -MultiViews

#-------------------------------------------------------------------------------
# Make index.php the directory index page
#-------------------------------------------------------------------------------
DirectoryIndex index.php 

to be continued…

 Signature 

Daniel Moore
http://www.danielwmoore.com
Using .htaccess to remove index.php

 
Posted: 19 April 2009 01:02 AM   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-09
234 posts

continued from previous post…

paste this to the end of the previous code block.

#-------------------------------------------------------------------------------
# Always make sure mod_rewrite is installed before using.
# If you are on a Linux server, uncomment the line with mod_rewrite.c
# If on a Windows server using XAMPP, uncomment the line with mod_rewrite.so
#-------------------------------------------------------------------------------
<IfModule mod_rewrite.c>
#<IfModule mod_rewrite.so>

  #-----------------------------------------------------------------------------
  # Turn on the RewriteEngine
  #-----------------------------------------------------------------------------
  
RewriteEngine on

  
#-----------------------------------------------------------------------------
  # Set the base directory where the application root is located.
  #-----------------------------------------------------------------------------
  # If your application is at http://www.domain.tld/path/to/CI_Application/
  # then uncomment the following line. Change /path/to/CI_Application/ to the
  # actual URL path not including the domain.tld (or localhost).
  # This includes using a subdirectory on localhost, like
  # http://localhost/path/to/CI_Application/
  #RewriteBase /path/to/CI_Application/

  # If your application is at http://www.domain.tld/ (or is http://localhost/)
  # then uncomment the following line.
  
RewriteBase /

  
#-----------------------------------------------------------------------------
  # The following 2 lines will force a www.prefix.  If you want to make sure
  # your site always displays the www subdomain, then uncomment the following
  # 2 lines.
  #-----------------------------------------------------------------------------
  #RewriteCond %{HTTP_HOST} !^www\.domain\.tld$ [NC]
  #RewriteRule ^(.*)$ http://www.domain.tld/$1 [R=301,L]

  #-----------------------------------------------------------------------------
  # The following 2 lines will remove a www prefix.  If you wish to remove the
  # www and always have http://domain.tld instead of http://www.domain.tld
  # then uncomment the following 2 lines.
  #-----------------------------------------------------------------------------
  #RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
  #RewriteRule ^(.*)$ http://domain.tld/$1 [L,R=301]

  #-----------------------------------------------------------------------------
  # If a controler can't be found - then issue a 404 error from PHP
  # Error messages (via the "error" plugin)
  #-----------------------------------------------------------------------------
  #ErrorDocument 403 /index.php/403/
  #ErrorDocument 404 /index.php/404/
  #ErrorDocument 500 /index.php/500/

  #-----------------------------------------------------------------------------
  # Deny any people (or bots) from the following sites: (to stop spam comments)
  #-----------------------------------------------------------------------------
  #RewriteCond %{HTTP_REFERER} nienschanz\.ru [NC,OR]
  #RewriteCond %{HTTP_REFERER} porn\.com
  #RewriteRule .* - [F]
  # NOTE: If you are having trouble from a certain URL just
  # add it above to forbid all visitors from that site.

  #-----------------------------------------------------------------------------
  # You can also uncomment this if you know the IP:
  # Just place the IP address you wish to deny here.
  # You may use multiple IP addresses separated by a space.
  # You may also use a domain, tld, or a part thereof.
  # Deny from 192.168.1.1 127.0.0.1
  # Deny from .net example.com
  # The above will deny from example.com and from all .net locations.
  #-----------------------------------------------------------------------------
  #Deny from 192.168.1.1

  #-----------------------------------------------------------------------------
  # METHOD #1 of HIDING PHP FILES. (There is an alternate method further down.)
  # If the file is NOT the index.php file then
  # Hide all PHP files so none can be accessed by HTTP.
  # This may not be desirable in all cases.
  #-----------------------------------------------------------------------------
  #RewriteCond %{REQUEST_FILENAME} !index.php
  #RewriteRule (.*)\.php$ index.php/$1

  #-----------------------------------------------------------------------------
  # The following lines begin the conditional setup for removing index.php
  # Use either METHOD #1 or METHOD #2, but not both.
  #-----------------------------------------------------------------------------
  # METHOD #1
  # If you want to redirect all files and directories that do not exist (404)
  # then use the following 2 statements.  This is how
  # http://domain.tld/controller/ is redirected to http://domain.tld/index.php
  # because /controller/ doesn't really exist, so now CI can use the URL to
  # call the correct controller.  This is the standard and default method.
  
RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond 
%{REQUEST_FILENAME} !-

to be continued…

 Signature 

Daniel Moore
http://www.danielwmoore.com
Using .htaccess to remove index.php

 
Posted: 19 April 2009 01:05 AM   [ # 2 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-09
234 posts

Again, continued… Final part.  Paste all 3 code segments to make one super .htaccess file.

Sorry for the long comments, they are for the novices to help them learn.

You can trim down your copy of it for your own use easy enough.

# METHOD #2
  # If you want to redirect all files/directories that are not a request
  # for the following:
  # index.php, robots.txt, favicon.ico, /public/, /img/, /css/, /js/
  # then use the following statement.
  # If you have other applications that are non-CI integrated into your site,
  # Like a third-party forum or blog, then this will disable it.  Do not
  # use if you need to call third-party PHP files.
  #RewriteCond $1 !^(index\.php|public|img|css|js|robots\.txt|favicon\.ico)

  # ADDITIONAL REWRITE CONDITION: This may be used in addition to one of the
  # above METHODs.
  # METHOD #2 of HIDING PHP FILES: This is to be used exclusively of the
  # method #1 of hiding PHP files listed above.  Do not use both methods.
  # Explanation: If you would like to hide all  PHP files so none can be
  # accessed by HTTP, then use the following line.
  # NOTE: If you have other applications that are non-CI integrated into your
  # site, like a third-party forum or blog, then this will disable it.  Do not
  # use if you need to call third-party PHP files.
  # If you need heightened security against use of PHP files, see my tutorial
  # on how to properly protect your directories.
  # NOTE: I have not personally tested this condition yet.  If you have tested
  # it and verified it works or does not work, please contact me and tell me
  # about it. http://www.danielwmoore.com/contact.
  #RewriteCond %{REQUEST_FILENAME}\.php -f [NC]

  #-----------------------------------------------------------------------------
  # use the following line if CI is in the root of the URL.
  # You may need to use index.php/$1 or index.php?/$1
  # Try it with or without the ? after index.php to see which works for you.
  # GoDaddy accounts require the ?
  # My localhost with XAMPP on Windows also requires the ?
  # Most hosts work correctly without the ?, so try it without first unless
  # you know your host requires it.  It is placed here so you will know where
  # it goes in case you need it.
  # [NC] = no case - case insensitive
  # [L] = Last rule, last rewrite for this set of conditions
  # [QSA] = Query String Append, should be used to prevent all redirects from
  # going to your default controller, which happens on some server
  # configurations.
  #-----------------------------------------------------------------------------
  #RewriteRule ^(.*)$ index.php?/$1 [NC,L,QSA]
  
RewriteRule ^(.*)$ index.php/$1 [NC,L,QSA]

  
#-----------------------------------------------------------------------------
  # use the following if CI is in a sub-directory, and place this
  # file IN that subdirectory.
  # If your CI Application is at http://www.domain.tld/CI_Application/
  # Replace 'CI_Application' with the name of the sub-directory.
  # Try it with or without the ? after index.php to see which works for you.
  # See above for the reasons for the '?'.
  # Be sure that this matches the RewriteBase above.
  # [NC] = no case - case insensitive
  # [L] = Last rule, last rewrite for this set of conditions
  # [QSA] = Query String Append, should be used to prevent all redirects from
  # going to your default controller, which happens on some server
  # configurations.
  #-----------------------------------------------------------------------------
  #RewriteRule ^(.*)$ CI_Application/index.php?/$1 [NC,L,QSA]
  #RewriteRule ^(.*)$ CI_Application/index.php/$1 [NC,L,QSA]

#-------------------------------------------------------------------------------
# Don't forget to end the IfModule check for the rewrite engine.
#-------------------------------------------------------------------------------
</IfModule>

#-------------------------------------------------------------------------------
# If Mod_rewrite is NOT installed go to index.php
# Remember to use mod_rewrite.c for Linux and mod_rewrite.so for Windows.
#-------------------------------------------------------------------------------
<IfModule !mod_rewrite.c>
#<IfModule !mod_rewrite.so>
  
ErrorDocument 404 index.php
</IfModule

Now that it’s posted, please suggest anything that needs to be changed, added, improved, removed, etc.

I’ll put the tutorial up (not in the forum, as the posts would be too long) and post a link when the discussion on this shows it’s passed everyone’s approval.  Pleasing everyone is nearly impossible, but it is what I’m attempting with this .htaccess file.

The entire .htaccess file is at http://www.danielwmoore.com/remove_index_from_codeigniter to make it easier to copy.

The .htaccess file at http://www.danielwmoore.com/remove_index_from_codeigniter will always be the most up-to-date copy, and there will be additional instructions there on configuring CI for removing the index.php.

 Signature 

Daniel Moore
http://www.danielwmoore.com
Using .htaccess to remove index.php

 
Posted: 19 April 2009 04:56 AM   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2006-07-27
2617 posts

You should use either:

RewriteCond $!^(index\.php|public|img|css|js|robots\.txt|favicon\.ico

or

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond 
%{REQUEST_FILENAME} !-

It’s redundant to use both

Also, you’ve repeated a section twice.

 Signature 

Check out the Template Library
Oh yeah, I tweet, too (regarding CodeIgniter on occassion).

 
Posted: 19 April 2009 05:50 AM   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2007-06-10
2939 posts
Colin Williams - 19 April 2009 08:56 AM

You should use either:

RewriteCond $!^(index\.php|public|img|css|js|robots\.txt|favicon\.ico

or

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond 
%{REQUEST_FILENAME} !-

It’s redundant to use both

Colin is correct with this, use one method or the other, not both.

Also bear in mind that the latter choice may cause CI to run your application more than once if any resource’s cannot be found. ie: missing css files or images therein.

 Signature 

URI Language Identifier | Modular Extensions - HMVC | View Object | Widget plugin | Access Control library

 
Posted: 19 April 2009 08:26 AM   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-09
234 posts
Colin Williams - 19 April 2009 08:56 AM

You should use either:

RewriteCond $!^(index\.php|public|img|css|js|robots\.txt|favicon\.ico

or

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond 
%{REQUEST_FILENAME} !-

It’s redundant to use both

Thank you, I’ve gone back and documented each method and explain why someone would want to use either choice, and it now gives them a choice as in other areas. 

Colin Williams - 19 April 2009 08:56 AM

Also, you’ve repeated a section twice.

Please point out exactly what section is repeated twice.  I don’t see it.

If you’re talking about:

#-----------------------------------------------------------------------------
  # The following 2 lines will force a www.prefix.  If you want to make sure
  # your site always displays the www subdomain, then uncomment the following
  # 2 lines.
  #-----------------------------------------------------------------------------
  #RewriteCond %{HTTP_HOST} !^www\.domain\.tld$ [NC]
  #RewriteRule ^(.*)$ http://www.domain.tld/$1 [R=301,L]

  #-----------------------------------------------------------------------------
  # The following 2 lines will remove a www prefix.  If you wish to remove the
  # www and always have http://domain.tld instead of http://www.domain.tld
  # then uncomment the following 2 lines.
  #-----------------------------------------------------------------------------
  #RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
  #RewriteRule ^(.*)$ http://domain.tld/$1 [R=301,L] 

This is not repeating.  One section forces “www.” and the other section removes “www.”.

 Signature 

Daniel Moore
http://www.danielwmoore.com
Using .htaccess to remove index.php

 
Posted: 19 April 2009 02:05 PM   [ # 6 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-16
411 posts

Thank you for taking the time to re-document this file. I know that when I was first starting out I needed lots of help in understanding the different ways .htaccess could help with my sites.

Also, regarding hiding the PHP files I think that there is a better way to do it. The goal is to hide anything that contains a ___.php at the end (or whatever ext you use) so something like this might be better.

# If the file/dir is not real
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond 
%{REQUEST_FILENAME} !-d

# Or if they are trying to access a PHP file
# (Hide all PHP files so none can be accessed by HTTP)
RewriteCond %{REQUEST_FILENAME}\.php -f

RewriteRule 
^(.*)$ index.php?/$1 [QSA,L] 

Of course, I have not tested this method yet, but you get the idea.

 Signature 

My Blog, C2D, PHP Videos, Résumé, Super .htaccess, Extra hooks, and MicroMVC

 
Posted: 19 April 2009 06:31 PM   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-09
234 posts

@Xeoncross: I’ll have to test that method tomorrow.  I’m out of town today, so don’t have access to my computer to test.  I personally don’t have any reason to hide all .php files, since any .php files I have beside the main index.php reside in a directory with a “deny from all” .htaccess file, which I think is the best and safest method.

I’ll look into that method tomorrow and try to give the time to test it thoroughly.

 Signature 

Daniel Moore
http://www.danielwmoore.com
Using .htaccess to remove index.php

 
Posted: 19 April 2009 06:42 PM   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-16
411 posts
Daniel Moore - 19 April 2009 10:31 PM

I personally don’t have any reason to hide all .php files, since any .php files I have beside the main index.php reside in a directory with a “deny from all” .htaccess file, which I think is the best and safest method.

Unfortunately, the majority of the world uses shared-hosting so they don’t have that option. I even use it for some of my projects.  wink

:EDIT: sorry, I didn’t fully read that comment.

 Signature 

My Blog, C2D, PHP Videos, Résumé, Super .htaccess, Extra hooks, and MicroMVC

 
Posted: 20 April 2009 11:31 AM   [ # 9 ]   [ Rating: 0 ]
Avatar
Joined: 2006-07-27
2617 posts

Yep, Daniel. I was talking about that bit. My bad. This is a great resource you have provided.

 Signature 

Check out the Template Library
Oh yeah, I tweet, too (regarding CodeIgniter on occassion).

 
Posted: 20 April 2009 01:01 PM   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2007-12-31
159 posts

Do you think it would be possible to put this in the CodeIgniter docs after its been fully reviewed?

If not, I’ll continue to look these threads up. Otherwise, great!


It may also be useful to make this note:
If you have the user_guide folder in your app (during development), you would need an .htaccess in that folder containing the following line:

DirectoryIndex index.html 
 
Posted: 20 April 2009 01:48 PM   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-09
234 posts
Xeoncross - 19 April 2009 06:05 PM

Thank you for taking the time to re-document this file. I know that when I was first starting out I needed lots of help in understanding the different ways .htaccess could help with my sites.

Also, regarding hiding the PHP files I think that there is a better way to do it. The goal is to hide anything that contains a ___.php at the end (or whatever ext you use) so something like this might be better.

# If the file/dir is not real
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond 
%{REQUEST_FILENAME} !-d

# Or if they are trying to access a PHP file
# (Hide all PHP files so none can be accessed by HTTP)
RewriteCond %{REQUEST_FILENAME}\.php -f

RewriteRule 
^(.*)$ index.php?/$1 [QSA,L] 

Of course, I have not tested this method yet, but you get the idea.

I have to get busy on some real work today, so I won’t be able to test it today after all.  I’ve added it to the above .htaccess with notations, however, that it needs testing.  I included it as an “alternate” method of doing this, and have labeled both methods with method numbers and explained that they should be exclusive of one another.

I’d like someone who has time to test and confirm this method of hiding PHP files so that I don’t have to include a disclaimer nor have a line that “may not work” in that file.  If someone has tested or used this method and can confirm it works, then please respond in this thread and let me know.  Thanks.

@simshaun: Getting a better .htaccess added to the CodeIgniter docs with a better explanation of the different things you may have to do on different servers would be awesome.  The lack of it is exactly why I’m doing this.  It seems that someone asks how to do this several times each week, and that’s just the one’s who aren’t researching and finding the answer already in the forums, as it has been answered more times than I can count.  However, none of the answers have been a “this answer will work for everyone, no matter your setup” type of answer, which is what we’re trying to finally address.

 Signature 

Daniel Moore
http://www.danielwmoore.com
Using .htaccess to remove index.php

 
Posted: 14 June 2009 10:21 PM   [ # 12 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-16
411 posts

Another thing that could help with site SEO is to REQUIRE an ending forward slash on all pages so that our links don’t half point to site.com/page and half to site.com/page/ when they are the same page.

RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}[R=301,L] 
 Signature 

My Blog, C2D, PHP Videos, Résumé, Super .htaccess, Extra hooks, and MicroMVC

 
Posted: 01 August 2009 01:30 AM   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2007-10-12
149 posts

Just wanted to say thanks to everyone that contributed to creating, documenting and posting this resource. I have begun to use this with all of the sites I develop, and really enjoy the thoroughness of it.

 Signature 

Brent Christensen { lead . developer }
Pyfo Web Design & Development
.(JavaScript must be enabled to view this email address)  |  http://www.pyfo.ca

 
Posted: 18 May 2012 10:13 AM   [ # 14 ]   [ Rating: 0 ]
Joined: 2010-02-23
2 posts

This is really helpful, htaccess files are really painful to understand…

I have a problem though that I really would like to see a solution for. I am using the following line to rewrite the index.php:

RewriteRule ^(.*)$ index.php?/$1 [NC,L,QSA] 

If I remove the ‘?’ i get a Bad request from the server when having %_25 (%) in the url. The ? solves that problem. But this causes other URL encoding problems in CI. When using the ? some special characters are encoded to underscores (_) or breaks the rest of the uri.

For example, using %_5b ([) breaks the rest of the URL, if it is not preceeded by %_5d (]), than it is converted to underscore. %_20 (space) and + are are also converted to underscore.

What is actually going on here?

When looking at the URL with

$_SERVER["REQUEST_URI"

it looks fine, but when sending the URI segment through CI it gets converted as explained above.

I’m using

$config['uri_protocol'"AUTO"

in the config file. Changing this setting to anything else breaks the whole application, which also is weird.

 
Posted: 18 May 2012 05:58 PM   [ # 15 ]   [ Rating: 0 ]
Avatar
Joined: 2009-05-05
241 posts

You should include a “down for maintenance” bit in the file.

# For maintenance:
# If your IP address is the IP below - then dont re-write - it will let you through
RewriteCond %{REMOTE_ADDR} !^1\.1\.1\.1 

# If the person is requesting the maintenance page, also dont rewrite (prevent loops)
RewriteCond %{REQUEST_URI} !/maintenance.html$
# Otherwise rewrite all requests to the maintenance page 
RewriteRule $ /maintenance.html [R=302,L] 

This lets you turn your website off, directing all trafic to “maintenance.html” - while still allowing access to a specific IP (i.e. your own so you can upload changes and test before going live again)