Problems with haproxy reqrep

haproxy

Scenario

I've got a haproxy farm of 3 (apache) webservers. 2 are actively balanced, and the third is a backup normally.

Every so often, I want to take the third server out of the backup role and make it a 'patch' server. But I want to do this without changing the url (eg, I don't want to use patch.mysite.com)

What I want to happen is, I visit http://mysite.com/patch and have haproxy give the server a cookie for later use in an ACL, but remove the /patch and send a GET / to the backend server.

Where I'm at now is the ACL is working fine, but the reqrep is not removing the /patch request before sending it to the backend.

Config:

global
    log 127.0.0.1   local0 info

    maxconn 25000
    daemon
    spread-checks 2 

defaults
    log     global
    mode    http
    balance roundrobin

    option  httplog
    option redispatch
    option abortonclose
    option forwardfor
    option http-server-close

frontend webfarm :80 
  # FILTERING
  acl acl_patch path_end /patches

  use_backend patch if acl_patch
  default_backend default_farm

backend default_farm
  cookie SERVERID insert indirect
  server prod1 192.168.100.18:80 cookie live01 check
  server prod2 192.168.100.22:80 cookie live02 check weight 2
  server prod3 192.168.100.20:80 cookie live03 check backup

  # do not let this cookie tell our internal IP address 
  rspidel ^Set-cookie:\ IP=

backend patch  
  cookie SERVERID insert indirect
  server prod3 192.168.100.20:80 cookie live03
  reqrep ^([^\ ]*)\ /patch     \1\ /

  # do not let this cookie tell our internal IP address
  rspidel ^Set-cookie:\ IP=

The haproxy log still specifies a GET /patch being sent to the backend. What am I missing about reqrep (I don't care about anything after the /patch directory)?

Best Answer

First, your rule should also keep the HTTP version part.

Second, why don't you use the "force-persist" statement for this ? It's designed exactly for this role. Just find something in your request that makes it different from your visitors', set a cookie to access it, then you can use this server. This me chanism was made precisely for maintenance operations without having to make the server appear as up for other users.

Alternatively in your case you could also use the "redirect" method, as it supports the "set-cookie" option; In your frontend, you would then replace the use_backend rule with something like this :

redirect location / code 302 set-cookie SERVERID=live03 if acl_patch

Your browser would then learn this cookie and redirect to the /, where server 3 will handle the request. There's even a clear-cookie option that can be used to get rid of the stickiness if you want.