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


Reply via email to