HAProxy URL rewrite question/issue …

HAProxy version: v2.6.6

URL Frontend: http://haproxyserver.domain.com/application1
URL Backend: https://appserver1.otherdomain.com/

What I’m trying to achieve is that when a user visits http://haproxyserver.domain.com/application1, HAProxy gets the page at https://appserver1.otherdomain.com/ and send it back as http://haproxyserver.domain.com/application1

So, I want to rewrite “/application1” from the front to “/” in the back and send the response back as “/application1”. E.g. an image on the backend like https://appserver1.otherdomain.com/images/test.jpg should be send back as http://haproxyserver.domain.com/application1/images/test.jpg and so on.

My haproxy.cfg file without any rewrite config in it:

#---------------------------------------------------------------------
# PRD http frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  PRD-http-front
    bind *:80
    http-request add-header X-Forwarded-For %[src]
    http-request add-header X-Forwarded-Proto http

    mode http
    option httplog
    option forwardfor       except 127.0.0.0/8
    maxconn 10240

    # define acl's
    acl host_haproxy-stats hdr(host) -i haproxy-stats.domain.com

    ###################################
    ### decide which backend to use ###
    ###################################
    # HAProxy statistics page
    use_backend haproxy-stats if host_haproxy-stats

    # Other
    use_backend application1 if { path_beg /application1 }

    # default backend
    default_backend PRD-local-httpd

#---------------------------------------------------------------------
# haproxy-stats backend
#---------------------------------------------------------------------
backend haproxy-stats
    mode http
    option httpclose
    option forwardfor
    http-request add-header X-Forwarded-For %[src]
    http-request add-header X-Forwarded-Proto http
    server haproxy-stats 127.0.0.1:8888 check

#---------------------------------------------------------------------
# PRD-local-httpd backend
#---------------------------------------------------------------------
backend PRD-local-httpd
    mode http
    option httpclose
    option forwardfor
    http-request add-header X-Forwarded-For %[src]
    http-request add-header X-Forwarded-Proto http
    server HAProxy-Server haproxyserver.domain.com:8081 check

#---------------------------------------------------------------------
# application1 backend
#---------------------------------------------------------------------
backend application1
    mode http
    option httpclose
    option forwardfor
    http-request add-header X-Forwarded-For %[src]
    http-request add-header X-Forwarded-Proto http
    server appserver1 appserver1.otherdomain.com:443 check ssl verify none

This config doesn’t work because HAProxy will try to load https://appserver1.otherdomain.com/application1 in the backend, which doesn’t exist. I Already tried several rewrite settings in the backend config part without any success. Some examples:

http-request replace-path ^([^\ ])\ /application1/(.) \1\ /\2
http-request replace-path /application1(.*) / \1
http-request set-path %[path,regsub(^/application1/?,/)]

I Even tried this in the frontend:

acl app1 path_beg -i /application1/
http-request set-path  /%[path] if app1

I Googled for hours and tried many things but I can’t figure it out. Every help is much appreciated!

It sounds like you need to modify responses to add back the path when HAProxy responds on behalf of the backend server. This is typically done in the Location header.

A word of caution: Some apps will let you play with this. Others send file payloads that include a relative path as the app expects it, so modifying the location header causes a mismatch and breaks things.

Assuming your app allows you to play with the Location header, I think you’re looking for something like this in your backend:

backend application1
    http-request replace-path /application1(.*) / \1
    http-response set-header Location /application1%[path]

That’s just an example. You may need to play around with the values a bit to get it to work.

Thank you very much for your reply and effort.
Unfortunately, the config gives an error when validating the config file:

error detected in backend ‘application1’ while parsing ‘http-response set-header’ rule : sample fetch <path]> may not be reliably used here because it needs ‘HTTP request headers’ which is not available here.

:wink:

This passes configuration checks on my instance of HAProxy. I’m not set up for what you’re trying to do, so I’m not able to test it for actual functionality.

backend application1
    # Removes /application1 before sending it to backend.
    http-request replace-path /application1(.*) \1
    # Adds /application1 to location on response from backend.
    http-response replace-header Location (.*) /application1/\1

Once again, there’s a good chance your application won’t like a proxy doing this as it messes with relative paths. I pulled something like this off for a little while by removing /admin from the pi-hole web interface, but an update broke it. I ended up having to let the app set its own paths. If your application supports setting its own paths, that’s the best way to accomplish this.

With this settings the config validates but just gives “Bad Request”.
Like you said: I’ll experiment some more with the values to see if I can get it to work.
I’m well aware that it might never work if paths are not all relative and even then it still might not work. I Will also contact the app vendor to see if they can help by changing their web config to serve from a subfolder.

Thank you very much once again for your time and effort! Much appreciated!

1 Like