The nginx documentation says that the server_name directive supports regular expressions. I've been banging my head against the wall trying to get even a trivial regex working.
I want http://subdomain.mydomain.com to redirect to http://mydomain.com/subdomain
Here is my code.
server {
server_name "~^subdomain\.mydomain\.com$";
rewrite ^ http://mydomain.com/subdomain;
}
Also, potentially noteworthy. Further down in the nginx config file there is a rule:
server {
server_name *.mydomain.com
...
}
What am I doing wrong?
UPDATE:
It has been suggested that I not use regex for this... to offer a little more clarity: the trivial regex was simply for purposes of troubleshooting. The real regex will look more like...
server {
server_name "~^.*(cvg|cincinnati)\.fakeairport(app)?\.(org|com)$";
rewrite ^ http://fakeairport.com/cincinnati;
}
server {
server_name "~^.*(lex|lexington)\.fakeairport(app)?\.(org|com)$";
rewrite ^ http://fakeairport.com/lexington;
}
So it would be preferable to use regex.
To answer an old question to help others
using nginx 1.1.19 you can do the following:
server {
server_name ~^(?<subdomain>\w+)\.domainA\.com$;
location / {
rewrite ^ https://$subdomain.domainB.com$request_uri permanent;
}
}
The subdomain before domainA.com is matched and stored in variable $subdomain which then can be used in the rewrite.
This rewrites url like xxx.domainA.com to xxx.domainB.com with only one server directive.
Gotta love regex with NGINX!
As I often work with multiple domain-names and I like to keep my configs as clean and rock solid as possible I almost always use regex with nginx.
In this case I've solved it with the following regex:
server {
listen 80;
server_name ~^((?<subdomain>.*)\.)(?<domain>[^.]+)\.(?<tld>[^.]+)$;
return 301 $scheme://${domain}.${tld};
}
What this does is the following: every subdomain.domain-name.tld
that points to this server (ip address) is automatically redirected to domain-name.tld
.
So for instance www.myexampledomain.com
is redirected to myexampledomain.com
.
To answer the question, what you could also do is the following:
server {
listen 80;
server_name ~^((?<subdomain>.*)\.)(?<domain>[^.]+)\.(?<tld>[^.]+)$;
return 301 $scheme://${domain}.${tld}/${subdomain};
}
Now mysubdomain.myexampledomain.com
is converted into myexampledomain.com/mysubdomain
.
Above regex is great as you can throw anything at it that you like and it will convert it for you.
If you read the server_name matching rules, you'll see that prefix and suffix server_names are checked before regex names, but after exact hostnames. Since *.mydomain.com matches, the regex isn't tested. The fact that it's listed earlier in the config makes no difference. Since you're just trying to match a single hostname with your regex, a simple:
server {
server_name subdomain.mydomain.com;
rewrite ^ http://mydomain.com/subdomain$request_uri?;
}
server {
server_name *.mydomain.com;
# stuff
}
will work for you.
I know everyone is saying if is evil in nginx config files, but sometimes you can't get around any other way.
server {
server_name .mydomain.com;
if ( $host ~ subdomain.mydomain.com ) {
rewrite ^(.*) http://mydomain.com/subdomain$1;
}
}
Just as a comment. If you want to redirect all subdomain levels to first subdomain level, util when you use a wildcard SSL certificate for example, you could use:
server {
listen 80;
server_name ~^(.*)\.(?<subdomain>\w+).mydomain\.com$;
return 301 https://$subdomain.mydomain.com$request_uri;
}
server {
listen 80;
server_name ~^(?<subdomain>\w+).mydomain\.com$;
return 301 https://$subdomain.mydomain.com$request_uri;
}
The first is for redirect an http multiple level subdomain to the first subdomain level in https. And the next is for redirect the first level subdomain in http to the same subdomain in https.