Hello Joao Guimaraes,
The following lines should accomplish what you described in your email:
acl is_main_site hdr(Host) -i www.mysite.com mysite.com
http-request set-var(req.scheme) str(https) if { ssl_fc }
http-request set-var(req.scheme) str(http) if !{ ssl_fc }
http-request redirect code 301 location
%[var(req.scheme)]://%[req.hdr(Host),regsub(www.,,i),lower,field(2,'.')].mysite.com%[capture.req.uri]
if !is_main_site
Explained line by line, the ACL is_main_site prevents a redirect loop
(www.mysite.com redirected to mysite.www or some other terrible
monstrosity often found when dealing with redirects). I highly recommend
thoroughly testing any redirect before deploying to production, as
redirect loops are quite nasty to debug.
The second and third line define a variable req.scheme that is used to
redirect either to http or https versions of a site. If you're doing
HTTPS only, you can drop these two lines and hardcode the following line
to redirect directly to HTTPS:
acl is_main_site hdr(Host) -i www.mysite.com mysite.com
http-request redirect code 301 location
https://%[req.hdr(Host),regsub(www.,,i),lower,field(2,'.')].mysite.com%[capture.req.uri]
if !is_main_site
_Please note that set-var requires haproxy 1.7 or any later version.
_
Also, if you are not performing SSL termination on the HAProxy instance
doing the redirect you will probably need to read a header value (most
likely X-Forwarded-Proto) instead of using { ssl_fc } to correctly set
the req.var variable ( alternatively, you can use the header value
directly for e.g. X-Forwarded-Proto by starting the redirect with
%[hdr(X-Forwarded_Proto)]:// ).
Finally, the redirect itself can be explained:
http-request redirect code 301 location
%[var(req.scheme)]://%[req.hdr(Host),regsub(www.,,i),lower,field(2,'.')].mysite.com%[capture.req.uri]
if !is_main_site
As explained above, this part sets the HTTP scheme to either http;// or
https://
This part strips the www. prefix (if present) from e.g. www.mysite.fr to
leave only mysite.fr . The i flag in regsub means that a
case-insensitive match is performed. If you need to match multiple
patterns (e.g. pictures.mysite.fr, chain multiple regsub statements.
Lower simply turns everything lowercase.
Field does the magic in this redirect and splits the prepared header
string by the separator '.' into a list (starting with index 1). We are
only interested in the 2 part, that is, the TLD. Please note that any
insanity with ccTLDs
<https://en.wikipedia.org/wiki/Country_code_top-level_domain>
(mysite.co.uk), multilevel subdomains (my.pictures.mysite.fr) or similar
won't work with this redirect. If you need a redirect with general
support for those, I recommend using regirep. Alternatively, if you need
to cover just one ccTLD, you can use regsub to replace .co.uk with .uk
. Also, as Aleksandar Lazic mentioned in his reply, haproxy map files
are also an option. Map files might be more pleasant that regirep if you
need to handle something exotic.
capture.req.uri saves the whole URI (path + query_string) so if you
accessed mysite.fr/cute.php?cat the redirect would go to
fr.mysite.com/cute.php?cat . if you just used path, you would loose the
?cat query parameter at the end.
Hope this helps, My apologies for the longer email but covering the
general case of the problem requires mentioning the major caveats you
might experience. Turns out, rewriting URLs is a non-trivial (and rather
not-fun) exercise.
Let me know if you have any questions.
Best regards,
Bruno Henc
On 1/21/19 11:40 PM, Joao Guimaraes wrote:
Hi Haproxy team!
I've been trying to figure out how to perform automatic redirects
based on source URL transformations.
*Basically I need the following redirect: *
mysite.*abc* redirected to *abc*.mysite.com <http://mysite.com>.
Note that mysite.abc is not fixed, must apply to whatever abc wants to be.
*Other examples:*
*
*
mysite.fr <http://mysite.fr> TO fr.mysite.com <http://fr.mysite.com>
mysite.es <http://mysite.es> TO es.mysite.com <http://es.mysite.com>
mysite.us <http://mysite.us> TO us.mysite.com <http://us.mysite.com>
mysite.de <http://mysite.de> TO de.mysite.com <http://de.mysite.com>
mysite.uk <http://mysite.uk> TO uk.mysite.com <http://uk.mysite.com>
Thanks in advance!
Joao Guimaraes