Rewrite subdomain to existing folders - .htaccess

I have a folder structure like this:
public_html
...images
...v2020
...v2021
With mod_rewrite, I redirect to the folder v2021 and force to https://www.example.com. Now I struggle with adding subdomains. When I go to images.example.com I want the redirection to the folder images, with images.example.com being unchanged in the address field.
I tested the code in two parts separately, first is the forwarding towards https://www including subdomain. It works without subdomains, but if I add any subdomain it leads to nowhere.
RewriteEngine on
# "example.com" to "www.example.com" (and HTTPS)
RewriteCond %{HTTP_HOST} ^(example\.com) [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,R=301,L]
# HTTP to HTTPS (same host) - preserve subdomain
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
The second part as a minimal working example is the forwording of the standard domain (no subdomain) and subdomain forwarding to a debug script.
RewriteCond %{HTTP_HOST} ^www\.example\.com
RewriteRule ^((?!v2021/).*)$ v2021/$1 [L]
RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com
RewriteRule (.*) echo.php\?a=%1\&b=$1 [L]
The script works fine and outputs a="www" when using it with the upper condition, but it is not execute with the lower one. I get forwarded to nowhere.
Thanks for your help!

There seem to be several issues here...
RewriteCond %{HTTP_HOST} !^www\. [OR,NC]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,R=301,L]
You first rule redirects all your subdomains (every hostname that does not start www.) to www.example.com, so the subdomain is lost. You probably need to change the first condition so that it only redirects requests for example.com (the domain apex) to www.example.com. But you also need to split the HTTP to HTTPS redirect in order to preserve the subdomain (images etc.)
For example:
# "example.com" to "www.example.com" (and HTTPS)
RewriteCond %{HTTP_HOST} ^(example\.com) [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,R=301,L]
# HTTP to HTTPS (same host) - preserve subdomain
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ %1/$1 [L,NC,QSA]
This will result in an internal rewrite loop (500 error) since it repeatedly rewrites to subdomain/url-path resulting in subdomain/subdomain/subdomain/url-path etc. etc.
You need a condition to either only rewrite the direct/initial request (not rewritten requests), or check that the subdomain has not already been rewritten to a subdirectory of the same name.
However, this also rewrites the www subdomain, which I assume is not the intention, so another condition is required to exclude this.
For example, to only rewrite the initial request and exclude the www subdomain:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule (.*) %1/$1 [L]
By always rewriting the initial request and not explicitly checking that the subdirectory does not match the subdomain means that you can have a sub-subdirectory of the same name as the subdomain (if required). eg. /images/images/foo.jpg is not a problem.
The NC and QSA flags on the RewriteRule are not required. (Since it's already case-insensitive and you have no query string to append to.)
The REDIRECT_STATUS environment variable is empty on the initial request and set to 200 (as in 200 OK status) after the first successful rewrite, so by checking that it is empty it avoids a rewrite loop.
If you've configured a wildcard subdomain then you might want to check that the subdirectory exists before rewriting. (Although filesystem checks are relatively expensive, so this is probably best avoided if possible. Particularly when serving assets.)
RewriteRule ^((?!v2021/).*)$ /v2021/$1 [L]
This would seem to conflict with the above rule. Shouldn't this only apply to the www subdomain (the opposite of the above rewrite)? For example:
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^((?!v2021/).*)$ v2021/$1 [L]

Related

I can't apply two rules at the same time in htaccess

and thanks to read me.
My goal is to have the same htaccess code in local and production.
First, I need to rewrite example.com/index.php?action=somepage to example.com/somepage.
Second, I must rewrite http://example.com to https://example.com, but only in production, not on localhost.
So far this is my code:
RewriteEngine on
RewriteBase /
# For Ionos
RewriteRule ^([0-9a-zA-Z/\ -]+)(?:&([0-9a-zA-Z&=_\ -]+))?$ index.php?action=$1&$2
# $1 : route name and framework parameters
# $2 : classic $_GET parameters (&param=value)
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301]
When I use https:// to connect, no problem, the first rule concerning index and action apply.
When I use http://, the adress become https://, BUT the index/action rule doesn't apply.
Thanks a lot!
Edit : this works :
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301]
# For Ionos, http => https
RewriteRule ^([0-9a-zA-Z/\ -]+)(?:&([0-9a-zA-Z&=_\ -]+))?$ index.php?action=$1&$2
# $1 : route name and framework parameters
# $2 : classic $_GET parameters (&param=value)
But I have a last problem.
My folder in like this:
[] example
...[]public
......htaccess
...htaccess
The code shown above is the htaccess of public directory. The htaccess of example directory redirect to public:
RewriteEngine on
RewriteBase /
# for Ionos
RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ public/$1 [L]
The problem is while http://example.com redirect to https://example.com, http://example.com/somepage redirect to https://example.com/public/somepage and I can't remove the "public" part.
Thanks!
Your two rules "were" in the wrong order. Your external redirect (HTTP to HTTPS) needs to be before the internal rewrite. Your first rule (rewrite) would have still applied, but it would have resulted in an external redirect to index.php?action=... (exposing your internal file/URL structure).
However, you are also missing L flags on both these rules.
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301]
If this is in the /public/.htaccess file and the /public subdirectory is hidden (ie. it's being internally rewritten to) then you need to change the RewriteRule to read:
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
After the request is internally rewritten by the parent config, the REQUEST_URI server variable contains the full URL-path, including the "hidden" /public subdirectory, so if you redirect to REQUEST_URI it will expose the hidden subdirectory. Whereas, if you use a backreference to the matched RewriteRule pattern, which matches against a URL-path that is relative to the current directory then this naturally excludes the /public subdirectory.

re-direct a domain to a sub-domain + make it https

this is kinda an odd one:
I need my site to do two things (one of which is already working):
if a user tried to access the domain via HTTP:// it is replaced with https:// - this is for SEO in google and to make the user feel more secure -
the site folder that is used to load the website needs to be the subdomain folder of the site
Oddly the second part of this is working and I figured out - however I'm not sure how to merge these two requests:
HTACCSESS
RewriteEngine on
RewriteCond %{HTTP_HOST} ^trippy\.co\.nz$ [NC,OR]
RewriteCond %{HTTP_HOST} ^www\.trippy\.co\.nz$
RewriteCond %{REQUEST_URI} !update.trippy.co.nz/
RewriteRule (.*) /update.trippy.co.nz/$1 [L]
But I'm not sure how to make the site display as
https://trippy.co.nz/
I have tried:
RewriteEngine On
RewriteCond %{HTTP_HOST} update\.trippy\.co\.nz [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://update.trippy.co.nz/$1 [R,L]
but then the web address displays as: https://update.trippy.co.nz
and I need to remain as https://trippy.co.nz/
Any help here would really great and I know its a odd situation to be in.
THanks,
Wally
...but then the web address displays as: https://update.trippy.co.nz
You would seem to be redirecting to the subdomain itself, not the subdomain's subdirectory, as you appear to be doing in the first rule. You may also be putting the directives in the wrong order - the external redirect needs to go first - otherwise you are going to expose the subdomain's subdirectory, which does not appear to be the intention.
Try the following instead:
RewriteEngine On
# Redirect HTTP to HTTPS
RewriteCond %{HTTP_HOST} ^(www\.)?trippy\.co\.nz [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R,L]
# Rewrite all requests to the subdomain's subdirectory
RewriteCond %{HTTP_HOST} ^(www\.)?trippy\.co\.nz [NC]
RewriteRule !^update\.trippy\.co\.nz/ /update.trippy.co.nz%{REQUEST_URI} [L]
No need for the extra condition in the 2nd rule block, as the check can be performed directly in the RewriteRule and use the REQUEST_URI server variable instead of the $1 backreference in the substitution string.
That that R by itself is a temporary (302) redirect. You may want to change that to R=301 (permanent) once you have confirmed this is working OK.

Redirect http to https and www to non-www in .htaccess

First of all, I know there are lots of answers on this, but I don't actually find one that works. This is what I have in the .htaccess file right now, and I want to mention that it worked previously, but it does not anymore.
Redirect 301 /unt-de-cacao-de-plaja/filtre/producator/crisnatur/ /ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g
Options +FollowSymlinks
# Prevent Directoy listing
Options -Indexes
# Prevent Direct Access to files
<FilesMatch "(?i)((\.tpl|\.ini|\.log|(?<!robots)\.txt))">
Require all denied
## For apache 2.2 and older, replace "Require all denied" with these two lines :
# Order deny,allow
# Deny from all
</FilesMatch>
# SEO URL Settings
RewriteEngine On
# If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/
RewriteBase /
RewriteRule ^sitemap.xml$ index.php?route=extension/feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=extension/feed/google_base [L]
RewriteRule ^system/download/(.*) index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
# FORCE HTTPS AND NON WWW
RewriteEngine on
RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
As a mention, I will have a lot of Redirect 301 from old pages to the new ones since the entire structure has been changed.
And the links that I am redirecting inside my website come with "www" like:
https://www.example.com/unt-de-cacao-de-plaja/filtre/producator/crisnatur/
and needs to be redirected to:
https://example.com/ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g
Redirect to https and non-www
To instead redirect all requests to https and non-www, use the following code instead of the previous:
Canonical HTTPS/non-WWW
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [L,R=301]
</IfModule>
As before, place this code in the root .htaccess of your site. Here is what it's doing:
Checks if mod_rewrite is available
Checks if HTTPS is off, or if the request includes www
If either condition matches, the request qualifies and is redirected
to the https/non-www address
OR
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
A few issues, in order of importance:
You have your canonical HTTP to HTTPS and www to non-www redirects at the end of the file. By placing it at the end of the file, after your front-controller, it's simply never going to be processed for most requests. This needs to be near the start of the .htaccess file, before your front-controller.
You should avoid mixing redirects from both mod_alias (Redirect) and mod_rewrite (RewriteRule) in the same scope. Different modules execute at different times throughout the request, despite their apparent order in the config file. Since mod_rewrite is required for other redirects, you should convert the mod_alias Redirect directives to use RewriteRule instead.
For example:
RewriteRule ^unt-de-cacao-de-plaja/filtre/producator/crisnatur/$ /ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g [R=301,L]
You should include the canonical scheme and hostname in your URL redirects in order to avoid multiple redirects when requesting an "old" URL at a non-canonical scheme ot hostname.
For example:
RewriteRule ^unt-de-cacao-de-plaja/filtre/producator/crisnatur/$ https://example.com/ingrijire-corporala/unt-cacao/unt-de-cacao-pentru-plaja-100g [R=301,L]
Depending on what you mean exactly by "a lot of Redirect 301" - you should not be doing this at all in .htaccess and instead redirecting in your server-side script, once you have determined that the request will 404. This is to prioritise normal site visiters and not your redirects (that get executed on every single request).
RewriteCond %{ENV:HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Since you stated that these directives worked previously then I assume the use of the HTTPS environment variable is OK on your system. But note that, whilst this is relatively common, it's non-standard. (It implies the server is using some kind of SSL front-end/proxy.)
Note that the order of these rules will result in a double redirect when requesting http://www.example.com/<anything> (HTTP + www). Which is necessary if you are implementing HSTS, but otherwise, you should reverse these two rules to avoid this unnecessary double redirect.

https to http while keeping path

I have here a little problem with a website and its WordPress blog.
For a short time, we had setup everything with https, until we were facing some issues and had to go back to HTTP.
Back then, I had a little collection of .htaccess files to deal with these kinds of problems, but I never actually tried my "non-www to www - ssl"
The intent was to add www and redirect https to http
RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/ [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Seemed pretty simple to me and I thought it should work.
I have two .htaccess files, one for http://www.example.com/ and one for http://www.example.com/blog both with the same content, as users are primarily coming from SE's via Blog.
The Problem is: If I load https://www.example.com/blog I get redirected to http://www.example.com/ instead of http://www.example.com/blog.
While writing the Question I thought I try this Question I had the idea to add this
RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
but then I get only redirected to http://www.example.com/{REQUEST_URI}
Could someone please tell me how I can keep the path on that redirect query?
RewriteCond %{HTTPS} on
RewriteRule ^/?$ http://%{SERVER_NAME}/{REQUEST_URI} [R=301,L]
If you notice that in your other directive you have %{REQUEST_URI}. You are missing the % prefix above. This is required syntax in order to get the value of the REQUEST_URI server variable. But also note that the value of REQUEST_URI already includes a slash prefix, so the slash should be omitted from the substitution. ie. instead of /{REQUEST_URI} it should be %{REQUEST_URI}.
Also note that the RewriteRule pattern (^/?$) only matches the root of your site (or /blog subdirectory if this .htaccess file is in that subdirectory). You need to match everything. So, modify the above RewriteRule like this:
RewriteRule ^ http://www.example.com%{REQUEST_URI} [R=301,L]
I've also hardcoded the domain, otherwise, you'll end up with a double redirect when requesting the non-canonical (ie. non-www) host.

htaccess non www to www and remove subdomain www

So I've got the following rewrite code in my htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [L,R=301]
//
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.([^\.]*)\.domain\.com$ [NC]
RewriteRule (.*) http://%1.domain.com$1 [R=301,L]
Works perfect for redirecting non-www to www for my domains.
I've got a subdomain, lets call it 'sub.domain.com' which works find. If I goto www.sub.domain.com, it redirecting to 'sub.domain.com/sub/'
Anyone having a idea why?
None of the rules you have in your question routes requests to a subdomain's folder. The /sub/ should never be there if it wasn't originally in the request.
That said, all of your redirect rules need to come before any routing rules. Routing rules being stuff that internally routes requests to other URI's, for example:
RewriteCond %{HTTP_HOST} ([^\.]*)\.domain\.com$ [NC]
RewriteRule (.*) /%1/$1 [L]
That rule internall routes to a folder named the same thing as the subdomain. If this rule were to be before the redirect, both rules get applied and the redirected URI becomes /sub/. You need your routing rules placed after your redirect rules, e.g. all rules that have a http:// or an R flag.

Resources