URL rewrite with HTTPS / www not working for subpages - apache

I have to following configuration in my .htaccess. The first rule puts https before the URL and the second puts www before the URL, if not set already.
# https redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# www redirect
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
These redirects work perfect for the homepage. However, if you call a subpage, these rules wont work.
domain.xy -> https://www.domain.xy (works, Homepage)
domain.xy/contact -> http://domain.xy/contact (doesnt work)
The weird thing is, the favicon get redirected correctly. Example with the contact page, as seen on
this picture.
How can it be, that my configuration only works for the toplevel, not for any subpage?

I'd say your RewriteRule is wrong. It should be .* instead of ^:
# https redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# www redirect
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

The problem was another rule in the .htaccess-File. Our hosting provider automatically generates a .htaccess suiting the Typo3 installation. I had to place my rewrite rule before the following lines:
# If the file/symlink/directory does not exist => Redirect to index.php.
# For httpd.conf, you need to prefix each '%{REQUEST_FILENAME}' with '%{DOCUMENT_ROOT}'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]
This rules, as far as i understand, redirects any request, which is not a file, directory or symlink back to the index.php. So in my case if i call domain.xy/contact, it redirects back to the index.php.
Because this rule has the [L] flag at the end, the .htaccess stops processing here. So i moved both my rules above this block and they get called before this block comes to action.

Related

.htaccess rewrite in subdirectory

I am currently deploying a number of sites from one hosting account. I have all of the sites in their own folder including the primary domain. The issue I have is when I rewrite the primary domains address with my current code, it includes the subdirectory in it. So currently if I type in http://www.example.com/url it rewrites to https://example.com/folder/url. I just want it to rewrite without the folder.
Any ideas. I know I am complicating this by running my primary domain in a subdirectory, just trying to clean up hosting as best as possible.
In my public_html .htaccess file:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/folder/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /folder/$1
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ folder/index.php [L]
and in public_html/folder .htaccess:
RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
So currently if I type in http://www.site.whatever/url it rewrites to https://site.whatever/folder/url.
This is a "redirect", not a rewrite.
This is happening because of the use of the REQUEST_URI server variable in your HTTP to HTTPS redirect in your public_html/folder .htaccess file:
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
The REQUEST_URI server variable contains the full URL-path of the request, which, by the time the subdirectory's .htaccess file is called, has been updated to contain /folder.
You need to either:
Move your canonical www to non-www and HTTP to HTTPS redirects to the .htaccess file in the document root. (This would be preferable if you have no other mod_rewrite directives in your public_html/folder .htaccess file.)
OR,
Modify the above directive to use the $1 backreference (to the captured RewriteRule pattern) as you are doing in the preceding www to non-www redirect. For example:
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
(Note that this should ultimately be a 301 redirect, once you have confirmed it works OK.)
And don't forget to escape literal dots in the regex.

How can I stop a single URL POST being changed to a GET redirect in .htaccess

I have about 40 c# desktop applications that are doing a POST off to http://www.example.com/submit-bug for user generated bug reports.
However I've recently switched my website (where the POST data is handled) over to HTTPS so everything is now 301'ed to HTTPS via htaccess.
This also means that my POST to http://www.example.com/submit-bug is being 301'ed to https://www.example.com/submit-bug which causes all the POST data to be lost as it goes from POST to a GET redirect.
How can I tell htaccess to ignore the redirect with a post to http://www.example.com/submit-bug and just continue to do the normal index.php routing that Laravel uses.
I've tried all sorts of combinations of the L and P flags but they are either ignored or cause a 500/404 error.
This is my current htaccess
RewriteEngine On
#RewriteCond %{REQUEST_URI} (.*)submit-bug(.*)
#RewriteRule ^ index.php [L]
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
# [NC] is a case-insensitive match
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
You can remove any redirections or rewrite regarding a POST, by adding at the beginning, before RewriteCond %{HTTPS} off:
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^ - [L]

Redirect subdomain to folder infinitely redirects due to www rule

I'm trying to add a single subdomain to an existing website. We've added the appropriate 'A' record. We want staging.example.com to display the contents from example.com/test/ (and remain staging.example.com).
The .htaccess file (written by someone else) redirects all non-https to https, and all non-www to www:
RewriteEngine On
RewriteBase /
#Rewrite http to https
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]
#Rewrite non-www to www
RewriteCond %{HTTP_HOST} !^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://www\.%{HTTP_HOST}/$1 [R=301,L]
I tried to add a line like the following, just before the last RewriteRule:
RewriteCond %{HTTP_HOST} !^staging\.(.+)$ [NC]
However, it always gets in a redirect loop to www.staging.example.com ...
Suggestions much appreciated.
This is because you are directing BACK to HTTP with your WWW redirect. Change it to https:
EDIT
I would also invert your statments .. This is EXACTLY what I use -- And I can verify it works for me:
RewriteEngine On
# to www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# to https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

https rules for htaccess including www redirect and removal of ".html" extensions

Currently my .htaccess looks like this and works perfect for http.
It redirects to www. and removes the .html file extension.
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC,L]
I have tried the .htaccess from this answer but still the site in question is completely messed up. E.g https://example.com/work shows a 404.
Also all images that are linked in the source code with /img/example-01.jpg do not show.
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Can you please help me with getting a .htaccess file that:
1.
Redirects to https
2.
Redirects to www. subdomain
3.
Removes .html from file extension so that example.com/work shows the work.html page.
Thank you for your help.
If your current .htaccess works fine, this modification should do:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [OR]
RewriteCond %{REQUEST_SCHEME} !https
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC,L]

How to stop htaccess rewrite rule updating browser URL

I've read through many of the similar requests such as:
Apache rewrite rule - prevent rewritten URL appearing in browser URL bar
But I can't figure out what I'm doing wrong, any help would be much appreciated.
I'm using codeigniter 3 and it's root is at the following location:
https://example.com/api/v1.0
I've set up a basic route and all is working fine with Codeigniter E.g. If I navigate to:
/api/v1.0/index.php/pages/view/about
the appropriate page appears so all seams well. What I really want is for the URL to get rewritten so that when I enter:
/api/v1.0/pages/view/about
it goes to the same page. I've added a htaccess file that rewrites the rule and all works as expected:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /api/v1.0/
RewriteCond $1 !^(index.php|resources|robots.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
The problem is, when I enter the the url:
/api/v1.0/pages/view/about
it goes to the correct page, but the browser URL gets updated to:
/api/v1.0/index.php/pages/view/about
My question is, how can I stop the browser URL from being updated?
Update - my web servers site behind an AWS ELB that acts as the https end point. I have the following in the httpd.conf to ensure that any non 'www' prefixed URLS and any http calls are redirected to https://www
<VirtualHost *:80>
RequestHeader set X-Forwarded-Proto "http"
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} !^test\. [NC]
RewriteCond %{HTTP_HOST} !^signup\. [NC]
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
I don't think this rule is causing an issue as its not being invoked, I'm providing the correct prefix and protocol.
Many thanks in advance,
Rob
Check that index.php isn't set for $config['index_page'].
If it is change it to:
$config['index_page'] = '';
OK, after much testing it would appear that my virtual host settings in httpd.conf were causing the issue. If I removed these rules and then the local .htaccess rules worked exactly as expected.
I've removed the local .htaccess rules and added the following to rule to httpd.conf:
RewriteRule ^/api/v1\.0/([A-Za-z0-9-/]+)/?$ /api/v1.0/index\.php/$1 [NC,L,QSA] # Process API Call
My Virtual Host section now looks like this:
RequestHeader set X-Forwarded-Proto "http"
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} !^test\. [NC]
RewriteCond %{HTTP_HOST} !^signup\. [NC]
RewriteCond %{REQUEST_URI} !^/_hostmanager/
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteRule ^/api/v1\.0/([A-Za-z0-9-/]+)/?$ /api/v1.0/index\.php/$1 [NC,L,QSA] # Process API Call
So now calls to:
/api/v1.0/some/directory
Will get rewritten to this:
/api/v1.0/index.php/some/directory
And this happens without redirecting the browser or affecting the browser URL. What I don't understand is why this is not entering into an infinite loop as I have no rewrite precondition to check for calls to the /api/v1.0/index.php/*
Anybody know why this is no entering into an infinite loop?