Regex to match a domain with only one subdomain - regex

i'm trying to create a regex for my .htaccess that matches Domains that have only one subdomain
Example
test1.subdomain.ourdomain.de no match
subdomain.ourdomain.de match => redirect to default.subdomain.ourdomain.de
What I've got till now is this ugly thing:
^([a-z0-9_\-]+)\.([a-z0-9_\-]+)\.ourdomain\.de$
It matches test1.subdomain.ourdomain.de but not without test1. How to negate this correctly? My attempts with negative lookaheads did not work :-(
Try here: https://regex101.com/

This example htaccess will redirect from subdomain.ourdomain.de to default.subdomain.ourdomain.de, and there will be no match on http://first1.subdomain.ourdomain.de:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^subdomain.ourdomain.de$ [NC]
RewriteRule ^(.*)$ http://default.subdomain.ourdomain.de/ [R=301,NC,L]
To match any 1-subdomain URL, you need to use correct capture group with a corresponding RewriteCond:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^([^.]+\.[^.]+\.[^.]+)$ [NC]
RewriteRule ^(.*)$ http://default.%1/ [R=301,NC,L]
Input:
http://tes1.clothes.germany.de
Output: <NOTHING> as RewriteCond %{HTTP_HOST} ^([^.]+\.[^.]+\.[^.]+)$ [NC] condition was not met
Input 2:
http://clothes.germany.de
Output URL:
http://default.clothes.germany.de/

You can try this one:
^[^\.]+\.[^\.]+\.[^\.]+$
Here ^[^\.]+ will match the pattern upto a . at the beginning of the line, then we have matched a literal ., then match upto a ., then again . and then at the last we match any pattern that does not have . at the end of the line.

Related

RewriteRule to handle one domain two folders to two domains no folder

I am attempting to create rewrite rules to handle some specific website redirections:
I would like domain1.ca/folder1/xyz to go to domain2.ca/xyz and domain1.ca/folder2/xyz to go to domain3.ca/xyz
Right now my attempts are as following:
RewriteCond %{HTTP_HOST} ^domain1.ca$ [OR]
RewriteCond %{HTTP_HOST} ^www.domain1.ca$
RewriteRule ^(\/folder1\/)(.*)$ "https://domain2.ca/$1" [R=301,L]
RewriteCond %{HTTP_HOST} ^domain1.ca$ [OR]
RewriteCond %{HTTP_HOST} ^www.domain1.ca$
RewriteRule ^(\/folder2\/)(.*)$ "https://domain3.ca/$1" [R=301,L]
Any help would be greatly appreciated :) Thx.
A couple of problems with your existsing rules:
In .htaccess the URL-path matched by the RewriteRule pattern does not start with a slash. So, the URL-path starts folder1/xyz, not /folder1/xyz.
You are unnecessarily capturing "folder1" in the first parenthesised subpattern and using this in the substitution string (ie. $1). You should be using $2, or don't capture the first path segment.
The directives could also be tidied up a bit (eg. no need to backslash-escape slashes in the regex and the conditions can be combined).
Try the following instead:
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.ca [NC]
RewriteRule ^folder1/(.*) https://domain2.ca/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.ca [NC]
RewriteRule ^folder2/(.*) https://domain3.ca/$1 [R=301,L]
Additional notes:
The end-of-string anchor ($) following (.*)$ in the RewriteRule pattern is not required since regex is greedy by default.
You only need to surround the argument in double quotes if it contains spaces.
I removed the end-of-string anchor ($) from the end of the CondPattern to also match fully qualified domain names that end in a dot.
I added the NC flag to the condition. It's technically possible that some bots can send a mixed/uppercase Host header.
Test first with 302 (temporary) redirects to avoid potential caching issues.

.htaccess redirects aren't respecting my regex

I need to redirect any requests with query strings from a set of origin URLs back to a thank you page.
For example, I need to redirect:
http://example.com/test1/test2/[origin]/?id=1
back to
http://example.com/thank-you
The way I've got it set up in my .htaccess file is as such:
RewriteEngine On
RedirectMatch 302 ^/test1/test2/(.*)/.+ /thank-you
I've tested the regex I'm using in an online regex tester and it appears to work as expected, so I'm confused as to why the redirect isn't taking place. Here's the link to that.
Obviously, I had to add backslashes to escape the slashes in the URL in the regex tester, but based on my understanding of how .htaccess evaluates regex, these aren't necessary.
My question is: the redirect works perfectly from the page without the query string if I remove the .+ from the end of the regex string, meaning that the beginning part of the regex works fine. I don't understand why the query string isn't matching the regex I've created.
I have also tried:
RewriteCond %{REQUEST_URI} ^/test1/test2/(.*)/
RewriteCond %{QUERY_STRING} id=([0-9]+) [NC]
RewriteRule (.*) /thank-you [R=302,L]
For your RedirectMatch, you may use:
RedirectMatch 302 ^/test1/test2/(.*)/(.*)+ /thank-you?
For your RewriteRule section, you may use:
RewriteCond %{REQUEST_URI} ^/test1/test2/(.*)/
RewriteCond %{QUERY_STRING} id=([0-9]+) [NC]
RewriteRule (.*) /thank-you [R=302,L,QSD]
First , no need to RewriteEngine On with mod_alias which is RedirectMatch at your rules use it with mod_rewrite , the second rules .
Try this :
RewriteEngine On
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$ [NC]
RewriteRule ^test1/test2/[^\/]+/$ /thank-you? [R=302,L]
I use ^id=([0-9]+)$ to restrict query string for a one that start with id and end with numerical value.
I remove this line RewriteCond %{REQUEST_URI} ^/test1/test2/(.*)/ becasue you could match against URI in RewriteRule as well.
If this rules wrok , change [R=302,L] to [R=301,L] to be permanent redirection.
Note: clear browser cache then test

.htaccess: append subdomain as query to existing queries

I'm trying to append the subdomain as a query to eventual existing queries using htaccess.
http://test.domain.com should be http://test.domain.com?x=test
http://test.domain.com?id=1 should be http://test.domain.com?id=1&x=test
This is what I have done, but it doesn't work and I can figure out why:
RewriteCond %{HTTP_HOST} ^([a-z0-9_-]+)\.domain\.com$ [NC]
// exclude www.domain.com
RewriteCond %1 !^(www)$ [NC]
RewriteRule ^[^\?]*(?:\?(.*))?$ index.php?$1&x=%1 [L]
My understanding was
[^\?]* all characters except ?, match 0 or more times
(?: start of a non capturing group
\? match ? literally
(.*) all characters after ? as a group
)? end of the non capturing group, match 0 or 1 times
But it does not work. Where is my mistake?
UPDATE 1:
I could make it work by using the following rule
RewriteRule (.*) index.php?$1&x=%1 [QSA,L]
http://test1.domain.com?y=test1 brings me [x=>test1,y=>test2]
but
http://test1.domain.com?y=test1&x=test3 brings me [x=>test3,y=>test2]
So it overrides my x value. Is there a way to block that?
UPDATE 2
This is the code I'm using now:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?!www)([\w-]+)\. [NC]
RewriteCond %1::%{QUERY_STRING} !^(.+?)::x=\1(?:&|$) [NC]
RewriteRule ^ index.php?%{QUERY_STRING}&x=%1 [L]
Try this rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?!www)([\w-]+)\. [NC]
RewriteCond %1::%{QUERY_STRING} !^(.+?)::x=\1(?:&|$) [NC]
RewriteRule ^ index.php?%{QUERY_STRING}&x=%1 [L]
Make sure this is the only rule you have in .htaccess while testing.
Explanation of:
RewriteCond %{HTTP_HOST} ^(?!www)([\w-]+)\. [NC]
RewriteCond %1::%{QUERY_STRING} !^(.+?)::x=\1(?:&|$) [NC]
We are capturing starting part of hostname from this group: ([\w-]+) which is denoted by %1. Note that we cannot use %1 in RHS of a condition.
We are then appending %1 and %{QUERY_STRING} together in %1::%{QUERY_STRING}. Here we could use any other arbitrary delimiter like ## as well.
In RHS we have ^(.+?)::x=\1(?:&|$) which means %1 followed by delimiter :: followd by literal x= and then \1 which is back-reference for %1 (goup before ::). ! before ^ is there to negate the condition. In simple words this condition means execute this rule only if we already don't have x=subdomain in QUERY_STRING.
Looks like you are trying to match the query string content with your RewriteRule’s pattern – that is not possible, it searches only the path component of the requested URL.
But, no worries – there’s an easy solution that helps combine the original query string, and what the pattern matched: The QSA flag.
So this should do the trick (combined with your existing RewriteConds):
RewriteRule (.*) index.php?$1 [QSA,L]

Rewrite a url string to corresponding folders

I want to have beautiful url and at the same time hide my folder structure,
I want the first Url to point to second Url,
image/f1_f2_girl.jpg
img/f1/f2/girl.jpg
I tried following but it did not work;
RewriteRule ^image\/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)$ img\/$1\/$2\/$3
how can I do Such using htaccess?
You regex needs to match for underscores in the regex pattern:
RewriteEngine On
# disable direct access:
RewriteCond %{THE_REQUEST} \s/+img/[^/]+/[^/]+/.+?\.jpg\s [NC]
RewriteRule ^ - [L,R=404]
RewriteRule ^image/([^_]+)_([^_]+)_(.+?\.jpg)$ /img/$1/$2/$3 [L,NC,R=302]
In your first URL you have _ not /.
And final .jpg (with .)
RewriteRule ^image/([a-z0-9]+)_([a-z0-9]+)_([a-z0-9.]+)$ img/$1/$2/$3 [NC,L]

Multiple fullstops in regex for RewriteRule

I use the following rule to redirect pretty urls from http://hostname.co.za/geoip/123.12.123.34 to http://hostname.co.za/geoip/index.py?ip=123.12.123.34
.htaccess in /geoip
RewriteEngine on
RewriteRule ^(.*\..*\..*\..*)$ /geoip/index.py?ip=$1
This works fine to match only ip's, but when I try this, it gives a 500 server error:
RewriteEngine on
RewriteRule ^(.*\..*)$ /geoip/index.py?ip=$1
I want to match not only ip's, but hostnames with at least one fullstop as well.
I have no idea why this shouldn't work...
The problem with the second pattern is that it also matches index.py and thus yields an infinite recursion. You can exclude that by using a RewriteCond:
RewriteCond $1 !=index.py
RewriteRule ^(.*\..*)$ /geoip/index.py?ip=$1
Furthermore, you should use a more specific pattern than .* like [^/.]+, so:
RewriteCond $1 !=index.py
RewriteRule ^([^/.]+\.[^/.]+)$ /geoip/index.py?ip=$1
RewriteRule ^([^/.]+\.[^/.]+\.[^/.]+\.[^/.]+)$ /geoip/index.py?ip=$1