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.
Related
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]
We have installed a SSL for our site and I have created an .htaccess with the following code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# mobile redirect
RewriteCond %{HTTP_HOST} ^www\mobile.example\.com [NC]
RewriteCond %
{HTTP_USER_AGENT}"android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule ^(.*)$ https://mobile.example.com/$1 [L,R=302]
</IfModule>
This code works great coming from the desktop, but the mobile part is not working. What am I missing?
...but the mobile part is not working.
You've not stated explicitly what the "mobile" part is expected to do. However, the "mobile part" in your code would seem to just be a www to non-www redirect. The HTTP to HTTPS redirect is separate to this and does not differentiate between mobile and desktop (and neither would it necessarily need to).
However, there are several issues with the directives in the "mobile part" that will prevent it from "working" (and also with the HTTP to HTTPS redirect).
The directives are in the wrong order. Both of the external redirects (HTTP to HTTPS and "mobile" www to non-www) should be before the internal rewrite (the first couple of rules)
I assume ENV:HTTPS (that references an environment variable called HTTPS) is as per instruction from your webhost. This is non-standard, although not uncommon with some shared hosts.
RewriteCond %{HTTP_HOST} ^www\mobile.example\.com [NC] - You are missing a dot after the www subdomain (assuming that is what you trying to match). So, this will never match. You are also missing a slash before the dot in the middle of the regex (to match a literal dot, not any character). The CondPattern should presumably read ^www\.mobile\.example\.com in order to match the www subdomain.
RewriteCond % {HTTP_USER_AGENT}"android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC] - You are missing a space after the first argument %{HTTP_USER_AGENT}<here>. Although you also appear to have an erroneous space after the %. Either way, this will fail to match. However, I would also question why you specifically need to match the mobile user-agent here? I would think you need to redirect www to non-www regardless of user-agent? Why would you permit a desktop user-agent access to www.mobile.example.com? So, this condition can perhaps be removed entirely.
Not a bug, but you probably don't need the <IfModule> wrapper, unless these directives are optional and you are porting the same code to multiple servers where mod_rewrite might not be available. See my answer to a related question on the Webmasters stack: https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary
Again, not a bug, but the RewriteBase / directive in this block of code is entirely redundant.
Taking the above points into consideration, it should be written more like this:
RewriteEngine On
# HTTP to HTTPS redirect - all hosts
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# mobile redirect
RewriteCond %{HTTP_HOST} ^www\.mobile\.example\.com [NC]
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteRule (.*) https://mobile.example.com/$1 [R=302,L]
# Front-controller
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Like I said in the notes above, I question the use of the RewriteCond %{HTTP_USER_AGENT} directive to detect mobile-only user-agents. If all users should be redirected www to non-www (as it looks like they should) then simply remove this condition. This should also presumably be a 301 (permanent) redirect once you have confirmed that it works as intended.
Taking this a step further, don't you also want to canonicalise desktop clients as well? ie. Redirect www to non-www on all hosts?
This code works great coming from the desktop
Although there's no reason why this didn't work "great" from mobile either if you were requesting the conanical host, ie. https://mobile.example.com/.
UPDATE: What I need for the .htaccess to do is redirect all traffic - desktop and mobile etc - to the new https instead of HTTP.
By the sounds of it you only need a "simple" HTTP to HTTPS redirect. The "front-controller pattern" that you have seemingly copied from the webhost's article may be in error?
Try the following instead in the root .htaccess file.
RewriteEngine On
# Redirect all requests from HTTP to HTTPS on the same host
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
You should remove all other directives and make sure there are no other .htaccess files in subdirectories.
The REQUEST_URI server variable contains the requested URL-path. This will be required, instead of using a backreference as you had initially, if your mobile subdomain points to a subdirectory off the main domain's document root (which you hint at in comments, but not stated in the question).
You must clear the browser cache before testing and test first with 302 (temporary) redirects before changing to a 301 (permanent) redirect only once you have confirmed the redirect works as intended.
When I set up my subdomain, I created some links incorrectly. Now Google thinks I have some pages on both my subdomain and my root domain. I need to fix this, but I can't redirect the entire subdomain.
Examples of what I want to do:
https://sub.example.com/ (no redirect)
https://sub.example.com/keep-1 (no redirect)
https://sub.example.com/keep-2 (no redirect)
https://sub.example.com/move-1/* => https://example.com/move-1/*
https://sub.example.com/move-2/* => https://example.com/move-2/*
I've tried a number of .htaccess solutions and I'm close, but I can't figure it out. Here's what I've tried:
Attempt #1 - Correctly redirects, but doesn't work as a solution because it redirects everything from the subdomain
RewriteCond %{HTTP_HOST} ^sub\.example\.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301,NE]
Attempt #2 - Doesn't redirect anything - Seems like the right solution but I'm missing something about how redirects work, I think...
RewriteCond %{HTTP_HOST} ^sub\.example\.com/move-1/ [NC]
RewriteRule ^(.*)$ https://example.com/move-1/$1 [L,R=301,NE]
Attempt #3 - Doesn't redirect anything
RewriteCond %{HTTP_HOST} ^sub\.example\.com/move-1/(.*)$ [NC]
RewriteRule https://example.com/move-1/$1 [L,R=301,NE]
Attempt #4 - Doesn't redirect anything
RewriteBase /
RewriteRule ^sub\.example\.com/move-1/(.*)$ https://example.com/move-1/$1 [R=301]
My .htaccess file is in the root domain's root html folder and seems to have control. I have also tried these from the subdomain's root folder, but that didn't redirect anything.
RewriteCond %{HTTP_HOST} ^sub\.example\.com$
RewriteRule ^move(.*) https://example.com/move$1 [R=301,L]
%{HTTP_HOST} is the host name, mapped to domain such as sub.example.com or example.com. It does not contain any path part, that follows behind the domain. $1 is back-reference, mapped to the regex part (.*). The RewriteRule tells if the request uri pattern starts with /move, then redirect to https://example.com/move$1 permanently.
I'm trying to redirect two kind of urls to a subdomain and all the others to my main domain.
A concrete example :
"my account" pages starting by /my-account/* and subscription page must be redirected to https://my-account.domaim.com. The uri must be kept.
all others like /news or the homepage must be seen on www.domain.com only
Here is what I have tried until now :
# All urls except my-account/* and subscription are redirected to the main domain
RewriteCond %{HTTP_HOST} ^my-account\.domain\.(.+)$
RewriteCond %{REQUEST_URI} !^my-account/
RewriteCond %{REQUEST_URI} !^subscription$
RewriteRule ^(.*)$ http://www.domain.%1/$1 [L,QSA,R=301]
# subscription page is redirected to my-account subdomain
RewriteCond %{HTTP_HOST} ^www\.domain\.(.+)$
RewriteRule ^subscription$ https://my-account.domain.%1/subscription[L,QSA,R=301]
# All my-account/* pages are redirected to my-account subdomain
RewriteCond %{HTTP_HOST} ^www\.domain\.(.+)$
RewriteRule ^my-account/(.*)$ https://my-account.domain.%1/my-account/$1 [L,QSA,R=301]
Each rules work independently but if i try all of them together i'm stuck in an infinite loop.
Is anyone have an idea how to prevent it ?
The rules look fine, but you have a missing space in your 2nd rule:
RewriteRule ^subscription$ https://my-account.domain.%1/subscription[L,QSA,R=301]
# -----------------------------------------------------------------^
But you can probably combine them into a single rule:
RewriteCond %{HTTP_HOST} ^www\.domain\.(.+)$
RewriteRule ^(subscription|my-account/.*)$ https://my-account.domain.%1/$1 [L,QSA,R=301]
Also make sure you're clearing your cache when you test, as 301 redirects are permanent and the browser will cache them.
Thanks for your answer !
The typos was from my copy/paste and the combination works but doesn't change anything to the problem with the other rules. I keep it for later ;)
I tried a reversed rules like this :
#RewriteCond %{HTTP_HOST} !^my-account\.domain\.(.+)$ [NC]
#RewriteCond %{REQUEST_URI} ^/subscription$ [OR]
#RewriteCond %{REQUEST_URI} ^/my-account/ [NC]
#RewriteRule ^(.*)$ https://my-account.domain.%1/$1 [L,R=301]
It also works but not in combination with the other. it doesn't loop anymore but if i try something like http/www.domain.com/subscription i'm redirected to www.domain.com with the url truncated. It seems that the Rewrite conditions aren't correctly recognized but still can't find why ...
I have two domains, let's say example.com and example.tld. But I want that users always get to the .tld domain. I want to use .htaccess and have tried
RewriteEngine on
RewriteRule ^(.*)$ http://example.tld/$1 [R=301,L,QSA]
When I open example.com, it redirects to example.tld. But when I open example.tld I get an error
This webpage has a redirect loop
How do I have to modify the redirection statement?
So you will need a RewriteCond to ensure that the subsequent RewriteRule is only applied when the requested HTTP_HOST was example.com.
RewriteEngine On
# Apply the rule if the host does not already match example.tld
RewriteCond %{HTTP_HOST} !^example\.tld$
RewriteRule (.*) http://example.tld/$1 [L,R=301,QSA]
Note that when using [R], the [QSA] is already implicit. You don't actually need to add it here but it doesn't hurt.
The above would redirect any domain other than example.tld into example.tld. If you added a third domain which you did not want to redirect (redirecting only example.com), instead of the negative match in RewriteCond, you could use a positive match for that domain only.
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule (.*) http://example.tld/$1 [L,R=301,QSA]