How to make HAProxy's SSL redirect and path rewrite (with reqrep) work at the same time?


#1

I need to deploy different apps on the same domain, thus I’ve set up the backend to rewrite URL with reqrep ^([^\ ]*\ /)appA[/]?(.*) \1\2. It works when I only deploy the HTTP or HTTPS version of the app.

However, if I try to redirect all HTTP traffic to HTTPS, it doesn’t work. The problem is that HAProxy has already rewritten the URL and stripped out the /appA part before the redirection. Thus if I try to visit http://myserver.com/appA, the page https://myserver.com will eventually be requested instead of https://myserver.com/appA.

I can’t put the redirect rule before the reqrep rule as it seems that HAProxy must process all the rewrites before the redirects.

What can I do to make my configuration work as I intended? This should be obvious but I can’t seem to find a relevant answer online.

My configuration:

frontend http_front
  bind *:80
  reqadd X-Forwarded-Proto:\ http
  acl appA_url url_beg /appA
  use_backend appA if appA_url

frontend https_front
  bind *:443 ssl crt /etc/haproxy/certs/myserver.com.pem
  reqadd X-Forwarded-Proto:\ https
  acl appA_url url_beg /appA
  use_backend appA if appA_url

backend appA
  reqrep ^([^\ ]*\ /)appA[/]?(.*)     \1\2
  redirect scheme https if !{ ssl_fc }
  balance roundrobin
  server web1 127.0.0.1:5001 check

#2

If I understand correctly this is your scenario

1- User sends a request to http://site.com/appA
2- haproxy redirect http to https
3- haproxy choose backend
4- haproxy needs to remove /appA from path and sends the request to backend .

frontend http-in
    bind 0.0.0.0:80
    http-request redirect scheme https
    default_backend maintenance

frontend https-in
    bind 0.0.0.0:443 ssl crt /etc/haproxy/certs alpn h2,http/1.1
    http-request add-header X-Forwarded-Proto https
    acl appA_url url_beg /appA
    use_backend appA if appA_url
    default_backend maintenance

backend appA
    balance roundrobin
    http-request set-uri %[url,regsub(^/appA,/,)] if { path_beg /appA }
    server web1 127.0.0.1:5001 check

backend maintenance
    balance roundrobin

#3

Thanks for the solution. Another one I got on Stackoverflow is:

http-request redirect scheme https if ! { ssl_fc }
http-request set-path %[path,regsub(^/appA/?,/)]

The key seems to be to use http-request instead of the older reqrep.