WWW Redirection in an HTACCESS File - .htaccess

I have an htaccess file for a React app at https://searchglutenfree.com/. I want it to automatically rewrite https://www.searchglutenfree.com/ to https://searchglutenfree.com/ while keeping all the params during the redirection.
I found this great default htaccess template on GitHub (https://gist.github.com/iheartmedia-matt/253ccb6183fdeaa5619f615f2cb5a58b), and getting the www to redirect is the last thing I need. Anyone know what I need to add and where in the file to get the WWW rewrite?
<ifModule mod_rewrite.c>
#######################################################################
# GENERAL #
#######################################################################
# Make apache follow sym links to files
Options +FollowSymLinks
# If somebody opens a folder, hide all files from the resulting folder list
IndexIgnore */*
#######################################################################
# REWRITING #
#######################################################################
# Enable rewriting
RewriteEngine On
# If its not HTTPS
RewriteCond %{HTTPS} off
# Comment out the RewriteCond above, and uncomment the RewriteCond below if you're using a load balancer (e.g. CloudFlare) for SSL
# RewriteCond %{HTTP:X-Forwarded-Proto} !https
# Redirect to the same URL with https://, ignoring all further rules if this one is in effect
RewriteRule ^(.*) https://%{HTTP_HOST}/$1 [R,L]
# If we get to here, it means we are on https://
# If the file with the specified name in the browser doesn't exist
RewriteCond %{REQUEST_FILENAME} !-f
# and the directory with the specified name in the browser doesn't exist
RewriteCond %{REQUEST_FILENAME} !-d
# and we are not opening the root already (otherwise we get a redirect loop)
RewriteCond %{REQUEST_FILENAME} !\/$
# Rewrite all requests to the root
RewriteRule ^(.*) /
</ifModule>
<IfModule mod_headers.c>
# Do not cache sw.js, required for offline-first updates.
<FilesMatch "sw\.js$">
Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
Header set Pragma "no-cache"
</FilesMatch>
</IfModule>

If you don’t need this to be dynamic regarding the host name, then I would add a Condition that checks if the host name started with www. after the one that checks for %{HTTPS} off, and add the [OR] flag to the former - and then simply hard-code the host name in the substitution URL of the following Rule.
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^(.*) https://searchglutenfree.com/$1 [R,L]
If you replace everything between the comments # If its not HTTPS and # If we get to here, it means we are on https:// in your .htaccess you had shown above with that, it should work.

In order to set up the desired redirect, www.example.com to example.com or vice versa, you must have an A record for each name.
To redirect users from www to a plain, non-www domain, insert this configuration:
in your .htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Related

.htaccess satisfy www/ssl rules before redirection

I've looked through tens of articles regarding this but none of them has solved my issue and it continues to give me a headache.
Here's what I want to achieve:
1) I have an second domain name which needs redirecting to the main domain while keeping the rest of the URL,
2) All files should lose .php extension,
3) Force WWW,
4) Force HTTPS.
Now the problem is that my current .htaccess only works this way for the main domain and only if the WWW condition is met. Let me explain.
If I type in domain1.com/page or domain2.com/page, it will open https:// www.domain1/2.com/page.php but it should only be /page without .php.
If I type in www.domain1.com/page, it will open https:// www.domain1.com/page - Expected behaviour,but if I type in www.domain2.com/page, it will open https:// domain1.com/page.php.
How can I make sure that any conbination of HTTP/HTTPS and WWW/non-WWW, domain1.com/domain2.com always redirects to https:// www.domain1.com/page ?
I'm also happy for any php code suggestions that I might put the top of every .php file to automatically redirect to the extensionless version but would really love to understand why my .htaccess isn't working.
Here's the code:
## Main Rules
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
## Redirect Domain2.com to Main
RewriteCond %{HTTP_HOST} ^www\.domain2\.com [NC]
RewriteRule ^(.*)$ https://www.domain1.com/$1 [R,L]
## Remove .php Extensions
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
## Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
## Force WWW
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
ErrorDocument 404 /404
Thanks a lot!
You have the directives in the wrong order. Importantly, the rule that appends the .php extension via an internal rewrite (which you've labelled "Remove .php Extensions") should go at the end, after the external redirects. Your rewrite is appending .php to the requested URL, ie. page becomes page.php and then you are triggering an external redirect which naturally exposes the underlying filename.
However, your directives will result in multiple redirects and can be simplified. The last redirect, for instance, does not canonicalise the protocol (and replies on previous rules to have done this).
For example:
ErrorDocument 404 /404
## Main Rules
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
## Redirect Domain2.com to Main
RewriteCond %{HTTP_HOST} ^(www\.)?domain2\.com [NC]
RewriteRule (.*) https://www.domain1.com/$1 [R,L]
## Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
## Force WWW
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
## Append .php Extensions
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*) $1.php [L]
If you have no intention of implementing HSTS then you should reverse the "Force HTTPS" and "Force WWW" rules in order to avoid an additional redirect when requesting http://domain1.com/page.
Note that your initial redirect from domain2.com to domain1.com is a 302 (temporary) redirect.
UPDATE: Note that MultiViews should also be disabled, if not already. For example:
Options +FollowSymLinks -MultiViews
If MultiViews was enabled, then this would also result in the first redirect exposing the file extension since mod_negotiation would issue an internal subrequest for page.php before mod_rewrite processes the request. However, if MultiViews was enabled, then this would also mean that your final rewrite rule that appends the .php extension was effectively being bypassed (since the 2nd conditon would always fail, unless page.php.php existed.).
With MultiViews disabled then this highlights a potential bug with the final rewrite. In that a request for /page/foo, where /page.php exists as an actual file (as in your example) would result in a 500 internal server error due to a rewrite loop. To correct this, the final rewrite rule that appends the .php extension should be changed to the following:
## Append .php Extensions
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
(There's no need to check that the request is not a directory and is a file, since it can never be both.)

Need to redirect to HTTPS using my current htaccess

I want to redirect HTTP and www to https://example.com.
I tried using:
# force HTTPS and www.
RewriteEngine On
RewriteCond %{HTTP_HOST} (?!^www\.)^(.+)$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]
But the result is only https://www. - the domain disappeared!
My current .htaccess:
<IfModule mod_rewrite.c>
# REWRITE ENGINE CONFIG
#ExpiresActive On
DirectoryIndex under_construction.html index.html index.php
#Header set Cache-Control "max-age=259200, public"
#ExpiresDefault "access plus 3 days"
#Header unset ETag
#FileETag None
# Expires header for static content
#<FilesMatch "\.(ico|jpg|jpeg|png|gif|js|css|swf|jgz|js.jgz)$">
#Header set Cache-Control "max-age=31536000, public"
#ExpiresDefault "access plus 11 months"
#</FilesMatch>
# Auth for non-public projects
#AuthName "ZEN 2.2 Login"
#AuthType Basic
#AuthUserFile /Applications/MAMP/htdocs/username/.htpasswd
#AuthUserFile F:/wamp/www/username/.htpasswd
#AuthGroupFile /dev/null
#require valid-user
# REWRITE CORE RULES RULES -- PLEASE DON'T MODIFY --
# THESE ARE THE MAIN REWRITES THAT MAKE THE ENTIRE WORLD SPIN
AddDefaultCharset UTF-8
# IF NO IMAGE FOUND
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} \.(gif|jpg|jpeg|png)$
RewriteRule .* resources/static/images/no_image.png [L]
RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1&%{QUERY_STRING} [L,QSA]
RewriteRule ^robots.txt$ resources/static/robots.php [L]
# gZip minified js files
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.jgz -f
RewriteRule (.*)\.js$ $1\.js.jgz [L]
AddType "text/javascript" .js.jgz
AddEncoding gzip .jgz
# gZip minified css files
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.jgz -f
RewriteRule (.*)\.css$ $1\.css.jgz [L]
AddType "text/css" .css.jgz
AddEncoding gzip .jgz
</IfModule>
Need some help adding the redirection to HTTPS and non-WWW to the current .htaccess file.
The problem when using code from here -> https://gist.github.com/vielhuber/f2c6bdd1ed9024023fe4
Is that the redirection is broken, and the result is https://www. only, no domain name is showing.
Try:
# force HTTPS and www.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [OR]
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%1%{REQUEST_URI} [R=301,QSA,L]
Some webservers don't create the HTTPS header when http protocol is used. So if HTTPS is not on (is off or null) this condition is true.
# force HTTPS and www.
RewriteEngine On
RewriteCond %{HTTP_HOST} (?!^www\.)^(.+)$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]
The problem with this code is, as the preceding comment suggests, it tries to redirect to www, not the domain apex. But it is also fundamentally flawed since the first condition is not always met (when HTTPS is off and www is requested), so the %1 backreference is not always set (so the domain name is omitted from the redirect - as you have found).
If you want a generalised (ie. without explicitly stating the hostname) solution then you would need to do something like the following instead:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\. [OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
The above rule block states... for all requests that are either for the www subdomain OR are for HTTP then redirect to HTTPS, less the www subdomain (if any) at the same URL-path.
The purpose of the 3rd condition - which must always match - is to simply capture the hostname less the www subdomain (if any). This is then referenced using the %1 backreference in the RewriteRule substitution.
NB: Test with a 302 (temporary) redirect first to avoid caching issues.
You will need to clear your browser cache before testing.
UPDATE: it is redirecting to domainname.com:443
That shouldn't be happening with the above directives, unless perhaps the port is explicitly included in the request? (But is that a redirect for http or https?)
You can try changing the 3rd condition to read:
RewriteCond %{HTTP_HOST} ^(?:www\.)?([^:]+)
Or hardcode the canonical hostname, which is arguably preferable and more reliable (without knowing your system). For example:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\. [OR]
RewriteCond %{HTTPS} off
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]
With this hardcoded solution, it cannot possibly redirect to anything other than the canonical URL - regardless of the request or system configuration.
EDIT#1: if I remove the htaccess file completely, the website still redirect to :443 if access from https
To help with debugging, try the following in your .htaccess file and then access https://your-domain.com/. What happens?
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule ^ - [F]
If you see a 403 Forbidden response then your web application would seem to be triggering this redirect. If not and you are still redirected then something in the main server config / virtual host would seem to be triggering the redirect.
EDIT#2: Yes, the response when i browse the https is 403 Forbidden.
That would seem to suggest that your web application is triggering this redirect.
And this would seem to be further backed up by the fact that you only seem to get this malformed redirect when requesting a valid URL, ie. one which only the app knows about. For example, https://example.com/contact (a valid page) is redirecting to http://example.com:443/contact (ERROR), but https://example.com/does-not-exist does not redirect (you get an application error / 404).

Site accessible with multiple URLs

I'm using the micro framework Silex on my website hosted on a VPS.
So, the site files are in the /site_name/public_html/ folder but, with Silex, the site must point to the /site_name/public_html/web/ folder.
In the public_html directory, I have the following .htaccess file :
Options -Indexes -MultiViews
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Redirect to https & www
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L,NE]
# Redirect incoming URLs to web folder
RewriteCond %{REQUEST_URI} !web/
RewriteRule (.*) /web/$1 [L]
</IfModule>
And, in the /public_html/web/ folder, the following .htaccess :
<IfModule mod_rewrite.c>
# Redirect incoming URLs to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
Now, everything works fine but my pages are accessible with three different patterns :
example.com/page/ (the one I want to keep)
example.com/web/page/
example.com/web/index.php/page/
I have used the meta canonical to avoid duplicate content but I still want these last two options to not exist.
I guess I have something to change in both .htaccess files but I can't find what it is.
I would actually remove the .htaccess file in the /web subdirectory altogether and rewrite directly to /web/index.php in the root .htaccess file. By having two .htaccess files you are seemingly creating extra work. The mod_rewrite directives in the subdirectory will completely override the parent directives (by default), so your canonical HTTPS and www redirects are also being overridden.
(Presumably you had a RewriteEngine On directive in the /web/.htaccess file?)
Having removed the /web/.htaccess file, try something like the following in your root .htaccess file:
Options -Indexes -MultiViews
RewriteEngine On
RewriteBase /web
# Redirect to https & www
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=302,L,NE]
# If /web or /index.php is present at the start of the requested URL then remove it (via redirect)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(?:web|index\.php)/(.*) /$1 [R=302,L]
# Front-controller...
# Internally rewrite all requests to /web/index.php (uses RewriteBase set above)
RewriteRule index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
The check against the REDIRECT_STATUS environment variable ensures we only test initial requests and not requests that have been later rewritten.
The <IfModule> wrapper is not required, unless your site is intended to work without mod_rewrite.
Note that a request like /web/index.php/page/ would result in two redirects. First to /index.php/page then to /page. Since this is an edge case I would consider a double redirect to be acceptable.
UPDATE: I've removed the "directory" check in the above as this would have prevented the document root (example.com/) from being rewritten to the /web subdirectory. This would have consequently resulted in a 403 if you didn't have a directory index document (eg. index.php) in the document root of your site. (However, requests for example.com/page/ should have still worked OK.)
Test with 302 (temporary) redirects and only change to 301 (permanent) when you are sure it's working OK - to avoid any caching issues in the browser. Be sure to clear the browser cache before testing.

Redirect to HTTPS except 1 page

Been looking all over for an answer but no response found could solve my problem.
I'm using the following .htaccess file to redirect users from a site to its https version :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS
# RewriteCond %{REQUEST_URI} !^/api-vop/
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e. http://www.example.com/foo/ to https://www.example.com/foo/
# The leading slash is made optional so that this will work either in httpd.conf
# or .htaccess context
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
I have first a rule to redirect to HTTPS then a rewrite rule for classic url rewriting to replace urls like myfile.php to /my-file
Thing is I need to let one url which is http://my-server.com/api-vop go through without being redirected to https, as seen by this line :
# RewriteCond %{REQUEST_URI} !^/api-vop/
Thing is I cannot get it to work, at best I'm trhown back to the index.php page.
Any solution anyone ?
Thanks in advance !
Keep your first rule as:
RewriteCond %{HTTPS} off
# This checks to make sure the connection is not already HTTPS
# RewriteCond %{THE_REQUEST} !\s/+api-vop/
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L,NE]
THE_REQUEST variable represents original request received by Apache from your browser and it doesn't get overwritten after execution of some rewrite rules. Example value of this variable is GET /index.php?id=123 HTTP/1.1

.htaccess file adding directories to URL

I have an htaccess file that is supposed to direct the user to a non www URL. Problem is, the site has directories that get added to the end of the URL when clicked on.
For example, subdomain.domain.com becomes subdomain.domain.com/folder/home.html, which is fine, but if the link is clicked again, it becomes subdomain.domain.com/folder/folder/home.html, and so on. Not so good.
Here is the .htaccess file:
RewriteEngine On
RewriteBase /
# Rewrite www.domain.com -> domain.com -- used with SEO Strict URLs plugin
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^subdomain\.domain\.com [NC]
RewriteRule (.*) http://subdomain.domain.com/$1 [R=301,L]
#
# or for the opposite domain.com -> www.domain.com use the following
# DO NOT USE BOTH
#
#RewriteCond %{HTTP_HOST} .
#RewriteCond %{HTTP_HOST} !^www\.sitehere\.com [NC]
#RewriteRule (.*) http://www.sitehere.com/$1 [R=301,L]
# The Friendly URLs part
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
# Make sure .htc files are served with the proper MIME type, which is critical
# for XP SP2. Un-comment if your host allows htaccess MIME type overrides.
#AddType text/x-component .htc
<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
Any help would be greatly appreciated.
Thanks!
check your base href tag in your templates and the system variable it outputs, I think it's ++site_url [you can check in your template what it actually is]

Resources