htaccess routing http to https sometimes includes removed CodeIgniter 'index.php'. Why? - .htaccess

I have the following mod rewrite rules - the first to remove the 'index.php' segment from URI requests and the second to force a HTTPS connection. However the second is reinserting the 'index.php'.
# send request via index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
# force SSL
RewriteCond %{HTTP_HOST} \.
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
For example -
http://www.mysite.tld/somepage
becomes
https://www.mysite.tld/index.php?/somepage
I'm still trying to understand how to write htaccess files but is there a way to combine these two to avoid this issue?

You need to swap the order of your rules.
# force SSL
RewriteCond %{HTTP_HOST} \.
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# send request via index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
When the redirect rule was last, it was still being applied because the first rule gets applied, rewriting stops for that iteration, then the rewrite engine loops, then the second rule gets applied and the URI (which now contains an index.php) gets redirected.

Related

How To Remove .cgi From URL With .htaccess?

I use a .cgi file to run python on my server. However, whenever someone goes to the site, it brings them to https://example.com/main.cgi/ (main.cgi is the name of the cgi file). Is there a way to remove this from the .htacess file, so it goes to https://example.com/ but still runs the cgi file?
This is the current .cgi file:
RewriteEngine On
RewriteBase /website
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /main.cgi/$1 [L]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
How can I make a RewriteRule that makes the URL / go to /main.cgi/ without it appearing in the URL?
You should make your https implementation as a first rule of your .htaccess file, could you please try following. Written as per your shown samples, please make sure you clear your cache before testing your URLs.
RewriteEngine ON
##Rule for applying https to non-http calls.
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
##Look for if any page doesn't have `/`slashes at the end then add it.
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.*)$ $1/ [R=301,L]
##Rules for non exiting file or directory to main.cgi file.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ main.cgi [L]
NOTE: Using RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE] personally gives me 1 slash at end so I had written a separate rule for adding trailing / for this one, to avoid 2 times / at the end of url.

htaccess redirect to index.php & force https/www problems

In my .htaccess file, I'm trying to achieve 2 things:-
1) Redirect any path to /index.php and pass the path as a query string, but keep the original URL
For example example.com/foo/bar would result in example.com/index.php?foo/bar behind the scenes but still show example.com/foo/bar in the address bar as the URL.
2) Enforce https & www
For example http://example.com/foo/bar would result in https://www.example.com/index.php?foo/bar behind the scenes but would show https://www.example.com/foo/bar in the address bar as the URL.
Below is what I have so far.
# Redirect to index
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
# When http isn't specified, it redirects to file with same URL
RewriteRule ^(.*)$ index.php?$1 [QSA]
## If no http2
RewriteCond %{HTTPS} off [OR]
## Or if http_host isn't www.
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
## Then rewrite
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=302]
With this, the redirect to index.php works as intended provided https and www are present in the original URL. This is because only the first rule block is triggered, whilst the second is skipped.
Though if either https or www aren't present, the resulting URL in the address bar is https://www.example.com/index.php?foo/bar not https://www.example.com/foo/bar as both rule blocks are triggered.
I'm wondering if these 2 different .htaccess rule blocks can be combined into one which fulfils the original requirements?
Thanks
Use this :
RewriteEngine on
# non www to www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
# http to https
RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
# foo/bar to index.php?a=foo&b=bar
RewriteRule ^([^/]*)/([^/]*)$ /index.php?a=$1&b=$2 [L]
For more rewriting URL logic use this https://www.301-redirect.online/htaccess-rewrite-generator
Recommended tool : https://www.generateit.net/mod-rewrite/

Rewrite Rule Adds ? to URL

I'm trying to redirect all URLs to https except ones that start with /feeds/. This is an ExpressionEngine site, so I also have to remove index.php from the beginning of the URLs. The hosting setup also requires that ? be at the end of index.php. Here's what I have:
RewriteEngine On
RewriteBase /
# Force SSL for everything but feeds
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^/(index.php\?*/)*feeds/ [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$2 [R,L]
# Remove index.php from ExpressionEngine URLs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
But when I go to http://www.mysite.com/feeds/blog, it gets redirected to https://www.mysite.com/?/feeds/blog.
I don't understand why this is happening. Here's the course of events as I see it:
http://www.mysite.com/feeds/blog is using port 80, so it meets the first condition
http://www.mysite.com/feeds/blog starts with /feeds/, so it fails the next condition and exits the rule
http://www.mysite.com/feeds/blog is not a file or directory, so it meets the next 2 conditions.
http://www.mysite.com/feeds/blog is changed to http://www.mysite.com/index.php?/feeds/blog and loops back to the top.
http://www.mysite.com/index.php?/feeds/blog is using port 80 and it starts with /index.php?/feeds/, so it fails the condition again and exits the rule
http://www.mysite.com/index.php?/feeds/blog does exist, so it fails the next 2 conditions and exits the rule.
The final server-side URL is http://www.mysite.com/index.php?/feeds/blog, and the client-side URL is still http://www.mysite.com/feeds/blog.
What's happening here? Where's that ? segment coming from?
Try this corrected code:
RewriteEngine On
RewriteBase /
# Force SSL for everything but feeds
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !/feeds/ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R,L,NE]
# Remove index.php from ExpressionEngine URLs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /index.php?/$1 [L]

Messy HTAccess File Gives Duplicate Homepage

I have the following HTAccess file:
ErrorDocument 404 /index.php?name=404
RewriteEngine on
# Add www. to any link without it
RewriteCond %{HTTP_HOST} ^mydomain\.co.uk$
RewriteRule ^(.*)$ http://www.mydomain.co.uk/$1 [R=301,L]
# Set homepage
DirectoryIndex index.php
# Rewrite content pages
RewriteRule ^sub1/([A-Za-z0-9_-]*)/$ index.php?sub1=1&name=$1
RewriteRule ^sub2/([A-Za-z0-9_-]*)/$ index.php?sub2=1&name=$1
RewriteCond %{REQUEST_URI} !^/404/
RewriteRule ^([A-Za-z0-9_-]*)/$ index.php?name=$1
# Make the pages without .php work
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php
# Forces a trailing slash to be added
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
This has gradually had bits and bobs tacked onto it and I now have a really small change to make, but can't work out how to do it.
The rules are basically there to ensure that all page have www and end in a /.
Most pages are in the form www.mydomain.co.uk/page/ which actually goes to mydomain.co.uk/index.php?name=page. There are two subdomains which pass an extra get param to the index.php.
The problem is that the homepage can be accessed from either www.mydomain.co.uk/ or www.mydomain.co.uk/index/.
How can I modify these rules so that if the user enters www.mydomain.co.uk it redirects to www.mydomain.co.uk/index/?
Try making the modification below to your .htaccess
### Existing Rules
# Add www. to any link without it
RewriteCond %{HTTP_HOST} ^mydomain\.co.uk$
RewriteRule ^(.*)$ http://www.mydomain.co.uk/$1 [R=301,L]
##New Rules
#if request for www.mydomain.co.uk
RewriteCond %{HTTP_HOST} ^www\.mydomain\.co\.uk$
#and it is for the home page, then redirect to index
RewriteRule ^$ http://www.mydomain.co.uk/index/ [L,R=301]
##Other Existing rules go here

Force trailing slash

I'm trying to force a trailing slash to my URLs, but I can't make it work the way I want. This is my .htaccess file:
RewriteEngine on
#Force trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !index.php
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ /$1/ [L,R=301]
#Subdomains
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} ^([^/.]+)\.example\.com$
RewriteCond $1/%1 !^([^/]+)/\1$
RewriteRule ^/([^/]+)? /%1%{REQUEST_URI} [L]
#Point everything to page.php
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond $1 !^(.*).(php|css|js|png|jpg|gif|htm|html)$
RewriteRule ^(.*)$ page.php?q=$1 [L,NC]
If I go to "en.example.com/about" I'm redirected to "en.example.com/en/about/", which is an invalid page.
How can I make this work?
The problem here is that the L flag causes a restart of the rewriting process with the rewritten URL (I’ve already told you that, didn’t I?):
Remember, however, that if the RewriteRule generates an internal redirect (which frequently occurs when rewriting in a per-directory context), this will reinject the request and will cause processing to be repeated starting from the first RewriteRule.
Now when /about is requested, the first rule get’s applied and redirects to /about/. The subsequent request of /about/ is then processed, at first the third rule is applied and the URL path is rewritten to /page.php. So far, so good.
But now the internal redirect takes place and the rewriting process is restarted with the new URL path /page.php. This is then fetched by the first rule again and redirected externally to /page.php/.
The second rule shouldn’t be applied at all as the pattern ^/ should never match as the per-directory path prefix is removed before testing the pattern when using mod_rewrite in an .htaccess file:
When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the pattern matching and automatically added after the substitution has been done.
But these rules should work:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ /$0/ [L,R=301]
RewriteCond %{HTTP_HOST} ^([^/.]+)\.example\.com$ [NC]
RewriteCond %1 !=www [NC]
RewriteCond $0/%1 !^([^/]+)/\1$
RewriteRule ^[^/]* /%1%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} !=www.example.com [NC]
RewriteCond $1 !.*\.(php|css|js|png|jpg|gif|htm|html)$
RewriteRule .* page.php?q=$0 [L]

Resources