31

real quick question regarding HAProxy reqrep. I am trying to rewrite/replace the request that gets sent to the backend.

I have the following example domain and URIs, both sharing the same domain name, but different backend web server pools.

http://domain/web1
http://domain/web2

I want web1 to go to backend webfarm1, and web2 to go to webfarm2. Currently this does happen. However I want to strip off the web1 or web2 URI when the request is sent to the backend.

Here is my haproxy.cfg

frontend webVIP_80
        mode http
        bind    :80
        #acl routing to backend
        acl web1_path path_beg /web1
        acl web2_path path_beg /web2

        #which backend
        use_backend webfarm1 if web1_path
        use_backend webfarm2 if web2_path
        default_backend webfarm1

backend webfarm1
        mode http
        reqrep ^([^\ ]*)\ /web1/(.*)     \1\ /\2
        balance roundrobin
        option httpchk HEAD /index HTTP/1.1\r\nHost:\ example.com
        server webtest1 10.0.0.10:80 weight 5 check slowstart 5000ms
        server webtest2 10.0.0.20:80 weight 5 check slowstart 5000ms
backend webfarm2
        mode http
        reqrep ^([^\ ]*)\ /web2/(.*)     \1\ /\2
        balance roundrobin
        option httpchk HEAD /index HTTP/1.1\r\nHost:\ example.com
        server webtest1-farm2 10.0.0.110:80 weight 5 check slowstart 5000ms
        server webtest2-farm2 10.0.0.120:80 weight 5 check slowstart 5000ms

If I go to http://domain/web1 or http://domain/web2 I see it in the error logs that the request on a server in each backend that the requst is for the resource /web1 or /web2 respectively. Therefore I believe there to be something wrong with my regular expression, even though I copied and pasted it from the Documentation. http://code.google.com/p/haproxy-docs/wiki/reqrep

Summary: I'm trying to route traffic based on URI, however I want HAProxy to strip the URI when it sends the request to the backend pool.

Thank you!

-Jim

Jim
  • 978
  • 7
  • 20
  • 32
  • There's an edit and comment buttons now. – Chris S Nov 07 '12 at 20:30
  • 1
    Jim, you're having a problem commenting because you're logged in with a different account than you used to create this question. Please try and keep your login account consistent so that this doesn't happen in the future. I've flagged a moderator to fix this. – MDMarra Nov 07 '12 at 20:30

3 Answers3

30

You have this:

reqrep ^([^\ ]*)\ /web1/(.*)     \1\ /\2

I think you want this:

reqrep ^([^\ ]*\ /)web1[/]?(.*)     \1\2

The difference being that the second one will work if the / after webN is omitted.

In answer to your comment below, going in to detail about how the expressions above work is more effort than I can give. However, maybe this will help.

Everything before /web1 is "capturing" everything that comes before web1 in the request string. So usually that would be GET or POST. The (.*) "captures" everything after web1, including nothing if there is nothing.

The next part (\1\2) says what to do with those captured parts. It says to form a string composed of \1 (the first captured part) and \2 (followed by the second captured part). Since web1 is never captured, it's not assembled in to the final output.

longneck
  • 22,793
  • 4
  • 50
  • 84
  • What does the \1\ \2\3 signify? Regarding the reqrep documentation what does the ^([^\ ]*)\ do? Here is the example given on the documentation page. # replace "/static/" with "/" at the beginning of any request path. reqrep ^([^\ ]*)\ /static/(.*) \1\ /\2 – Jim Nov 07 '12 at 20:40
  • After reading your comment, I realized that my proposed solution was slightly overly complicated. I simplified it. – longneck Nov 07 '12 at 20:53
  • So what is the reqrep syntax? reqrep {string_2_search_thru} {search_string} {replace_string}? I am confused as to the \1\ \2\3? – Jim Nov 07 '12 at 21:00
  • Is there a way to incorporate this reqrep to work if the user puts /web1 or /web1/ ? – Jim Nov 08 '12 at 01:56
  • Did you try it? – longneck Nov 08 '12 at 12:32
  • Yea, I get a 503:Bad Gateway if I try /web1. It works when I do /web1/ – Jim Nov 08 '12 at 15:01
  • oh, i see what was wrong. I updated the line again. Please try that. – longneck Nov 08 '12 at 15:42
  • Thank you! That works. if I do /web1 or /web1 or even /web1index.html, the default html page. It works – Jim Nov 08 '12 at 17:36
  • I suppose that correct one is `^([^\ ]*\/)web1[\/]?(.*)` – ipeacocks Dec 11 '16 at 23:17
  • +1 for explaining that the regexp matches against the first line of the HTTP request, the docs mention it, but did not register until I saw your explanation – Tony BenBrahim Jan 10 '17 at 01:21
  • How to do the same in HAProxy 2+ ? – Alexandre A. Mar 28 '20 at 23:57
5

Since HAProxy version 2.1, there's no reqrep directive. So you can use following:

http-request replace-path /web1(.*) \1
digz6666
  • 531
  • 8
  • 8
0

Put this on the frontend

reqirep  ^([^\ :]*)\ /(.*) \1\ /web1/\2

Good lesson learn to strip string: https://gist.github.com/PiBa-NL/8ad6c222354cbd7a5af5