how do I skip a RewriteRule if REQUEST_URI is a specific directory. This is a CodeIgniter project - apache

I have a CodeIgniter project running on CentOS, with an EV cert successfully installed.
I don't want SSL used when the /rss directory is accessed. I had this working, but I broke it somehow during an upgrade.
Here is my .htaccess file, which I think is correct:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# redirect to SSL connection
RewriteCond %{REQUEST_URI} !^/rss/
RewriteCond %{SERVER_PORT} 80
# R=301 sends HTTP Moved Permanently L=Last rule for this request
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
#previously this would not have been possible.
#'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#When your application folder isn't in the system folder
#This snippet prevents user access to the application folder
#Submitted by: Fabdrol
#Rename 'application' to your applications folder name.
RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
#Checks to see if the user is attempting to access a valid file,
#such as an image or css document, if this isn't true it sends the
#request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin
ErrorDocument 404 /index.php
</IfModule>
Going to the site, the url is correctly changed to https://www.site.com
But going to www.site.com/rss also gets changed to https.
I don't want it to use ssl for that directory.
I think the .htaccess file is correct, so maybe it is a CodeIgniter thing...
IF anyone has an idea, I would be very grateful.

What might be happening is that a mod_dir is not intervening in the order that it did before (mod_dir by default will redirect, if you access a directory but don't include a trailing slash, to the same URL with the trailing slash). If you try to access http://www.site.com/rss RewriteCond %{REQUEST_URI} !^/rss/ matches (since the request uri starts with "/rss" != "/rss/") and it gets rewritten to https://www.site.com/rss. Then mod_dir takes over and redirects you to "https://www.site.com/rss/". It's possible that before the upgrade, mod_dir applied the redirect first so you get redirected to "http://www.site.com/rss/" then the first condition (!^/rss/) fails, thus you don't get rewritten to https://
Try changing the first rewrite condition to:
RewriteCond %{REQUEST_URI} !^/rss/?$
So URI's like "/rss" and "/rss/" will fail the match and not get redirected to https://

Related

point root to sub-directory with .htaccess

i have the rule to redirect all request to https and point to index.php
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:CF-Visitor} !{"scheme":"https"}
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Protocols h2 http/1.1
the root directory is htdocs, but i need change it to point to htdocs/public because some framework implement public folder has root. the problem is that i fin that example:
RewriteRule ^subfolder/$ /yourfile.php [L]
It's not clear to me how to implement it.
update:
my .htaccess file is in the root directory: htdocs, then index.php is located in htdocs/public, in this subdirectory I don't have the .htaccess
finally what I am looking for is that when entering a url like:
https://your-example.com/
https://www.your-example.com/
https://www.your-example.com/test-foo/
https://www.your-example.com/test-foo?data=data&foo=foo
all these requests point to index.php in the subdirectory:
htdocs/public/index.php
update 2:
my current routing in /public/.htaccess:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
the root directory is htdocs, but i need change it to point to htdocs/public because some framework implement public folder has root.
Ordinarily, if you have access to the server config then you would "simply" change the DocumentRoot in the server config to point to the /public subdirectory. Alternatively, if you have access to the directory above the document root (as you appear to) then move the file structure "up" a level, so that the files in the /public subdirectory are moved to the document root (ie. htdocs/) and the framework/system files are in a directory above the document root, outside of the public HTML space (as they should be).
However, if you don't have access to the server config and/or are unable to move the files, and you have a /public subdirectory off the document root then proceed as follows...
I assume your current HTTP to HTTPS rule/redirect is working OK for you (since this is specific to Cloudflare)? However, the rule you posted does not route anything to index.php as you appear to suggest and the Protocols directive is not permitted in .htaccess (and should be triggering an error) - so not sure what that is doing there?
You need to add a rewrite to the root .htaccess file (ie. /htdocs/.htaccess) that rewrites all requests to the /public subdirectory. And create an additional .htaccess at /htdocs/public/.htaccess that routes all requests to public/index.php (your front-controller).
For example, try it like this:
# htdocs/.htaccess
RewriteEngine On
# Redirect HTTP to HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:CF-Visitor} !{"scheme":"https"}
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Rewrite all requests to the "/public" subdirectory
# You could do this unconditionally, depending on your requirements.
# ie. You don't necessarily need to check for existing files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) public/$1 [L]
Also consider canonicalising the www vs non-www hostname (ie. redirect one to the other). This would go in the root .htaccess file before or after the HTTP to HTTPS redirect (depending on requirements, ie. are you implementing HSTS?).
Create a second .htaccess file at htdocs/public/.htaccess with the following:
# htdocs/public/.htaccess
DirectoryIndex index.php
Options +FollowSymLinks -MultiViews -Indexes
RewriteEngine On
# Route all requests to "index.php" (front-controller)
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
UPDATE:
I quick analysis of your existing rules, but as I mentioned in comments, the version I described above is preferable.
my current routing in /public/.htaccess:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
The RewriteBase / directive here is incorrect and will break the rules when located in the /public subdirectory. This would need to be either set to RewriteBase /public or removed altogether (preferable).
The QSA flag is not required since you are not including a query string in the substitution.
^(.*)$ - the capturing group is less efficient and not required (you are not making use of any backreferences here).
The <IfModule> wrapper is not required and should be removed. This would only be required if these directives are optional (they are not) and you are moving these directives to multiple servers where mod_rewrite might not be enabled.
The filesystem checks to make sure the request does not map to a directory (!-d) and is not a symbolic link (!-l) are generally not required (and consequently is an unnecessary overhead if they are not reqd). These should be removed, unless you specifically need to access filesystem directories (or symbolic links) directly (which is rare).

http:// redirects to https://www.www with htaccess

I have a CI installation in my root domain. SSL certificate is installed and working properly. When I redirect http:// to https://www it redirects to https://www.www (an extra www), that too on some computers and some browsers as users have reported. However, when I remove 'www' from redirection, its all fine. Seems like www is looping. So far, I've digged my code hundred times, and see no sign of redirection from code (I mean addition of extra www). I'm doing it with htaceess. Any help will be highly appreciated. This is my htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
#Force SSL
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R,L]
#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
#previously this would not have been possible.
#'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php/$1 [L]
#Checks to see if the user is attempting to access a valid file,
#such as an image or css document, if this isn't true it sends the
#request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
I'm running it on apache with Centos VPS.
Thank you so much!
The HTTP_HOST is the "target host" part of the request, like: www.mydomain.com.
The REQUEST_URI is generally the path which was given in order to access a certain page; for instance, ‘/folder/index.html’.
In your RewriteRule you say to put 'www.' in front of the requested domainname.
You don't want that, when someone asks for http://www.yourdomain.com.
Without the www. in your RewriteRule someone who requests for http://yourdomain.com gets redirected to https://yourdomain.com
When you want to redirect to https and www you need to add conditions. Look into Apache docs on Canonical host and on questions/4083221/how-to-redirect-all-http-requests-to-https for this solution:
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTPS_HOST} !^www.yourdomain.com$ [NC]
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [L,R=301]

htaccess redirect to https works only if the file exists

I have a wordpress site with SEO Redirection Plugin installed. This because I have changed the site and I had to 301 redir some old pages.
Everything was working fine. Then I have also installed the SSL and I have changed the htaccess in order to redir from http to https. This is the file (as you can see, I have tested different solutions):
# RewriteEngine On
# RewriteBase /
# redirect 301 /implantologia.html https://www.mysite.it/implantologia/
# BEGIN GD-SSL
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTPS} !=on
# RewriteCond %{SERVER_PORT} !^443$
# RewriteCond %{HTTP_USER_AGENT} ^(.+)$
# RewriteRule ^$ https://www.mysite.it/$1 [R=301,L]
RewriteCond %{SERVER_NAME} ^mysite\.it$ [NC]
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301]
Header add Strict-Transport-Security "max-age=300"
</IfModule>
# END GD-SSL
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
This is what is happening now:
if I check for an existing file using http, everything works and the user is redirected to https;
if I check for a file that does NOT exist, using HTTPS, then my SEO Redirection plugin redir the request and everything is ok;
if I check for a file that does NOT exist (for instance an old external link to mysite.it, using HTTP), the url in the browser remains the same and I get a 404 error. But if I resend the request, it works and I go to the right page.
Finally, if you click on an old http link you get a 404 error. However, you will never experience this problem again after you have started to navigate on the site. I have a log of 404 error and it is full of errors that I wasn't able to see... until I started to browse Anonymously.
So, what kind of problem is this one? Is there a kind of cache? How come it doesn't work only for the first time access? Why htaccess doesn't redirect to https if the file requested doesn't exist?
Thank you in advance for your help.

CodeIgniter htaccess for subdomain without changing URL

I have been searching this but could not find the answer. I might have missed something here. Basically I have two applications under one CI installation. Each of the app will have their own subdomain. So for example http://foo.example.com/ which will redirect to http://example.com/foo and http://bar.example.com/ which will redirect to http://example.com/bar. The http://example.com/ itself will be some kind of a landing page.
The redirect part is working fine. But it keeps changing the URL from http://foo.example.com/ to http://example.com/foo, which I want to prevent. I have read a solution to use a [P] instead of [L] flag, but that will require me to enable proxy.
Is there any other option for me to do this other than enabling proxy?
Currently my htaccess file is as below:
RewriteEngine On
RewriteBase /
#Removes access to the system folder by users.
#Additionally this will allow you to create a System.php controller,
#previously this would not have been possible.
#'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php/$1 [L]
#Checks to see if the user is attempting to access a valid file,
#such as an image or css document, if this isn't true it sends the
#request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
# The line for subdomain
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ http://example.com/%1/$1 [L,NC,QSA]
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin
ErrorDocument 404 /index.php
Thank you very much for the response.

Mod_Rewrite rewriting directory I dont want it to

So I am using Kohana which is useful if you know it, but not needed to assist me.
I have the following mod_rewrite rules:
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/store/.*$
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php [L]
So I am trying to rewrite all requests for files and directories that do not exist to index.php.
However, I want any request sent to mydomain.com/store/* to go through as there is another htaccess file in the store directory that does work there. That does not seem to be working at the moment. Any ideas?
Full htaccess:
# Turn on URL rewriting
RewriteEngine On
# Installation directory
RewriteBase /
#ErrorDocument 404 http://www.mydomain.com/404Page.html
#Options +FollowSymlinks
# Protect hidden files from being viewed
<Files .*>
Order Deny,Allow
Deny From All
</Files>
RewriteCond %{REMOTE_ADDR} !^myip
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^(.*)$ http://www.mydomain.com/maintenance.html [R=307,L]
##301 Redirect Rules##
#some 301 redirects i did not include here
##Kohana Redirect Rules##
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system|kohana|vendors)\b.* http://www.mydomain.com/ [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/?store/
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php [L]
Try this condition:
RewriteCond %{REQUEST_URI} !^/?store/
There is no need to check the characters after the directory. I made the first slash optional if I remeber correctly is the first slash only visible if your server configuration does not contain a tailing slash.
The issue turned out to be in the .htaccess file in the store directory not the one in the webroot. Thanks all, and sorry for my stupidity. IF anyone wants to leave comments on how to debug something of this nature for future users that would be awesome.