0
votes

I'm trying to define a LUA hook in HAProxy so I can perform an action (kill the container processing the request) once I get the response. My problem here is dealing with the HAProxy buffer. I've tried different implementations and this is the closest one to work (although half of the times doesn't send back to the client all the data):

function hook(txn)
  local in_len = txn.res:get_in_len()
  while in_len > 0 do
    txn.res:forward(in_len)
    local out_len = txn.res:get_out_len()
    while out_len ~= 0 do
      core.yield()
      out_len = txn.res:get_out_len()
    end
    in_len = txn.res:get_in_len()
  end
  os.execute("docker rm -f server_" .. txn.sf:srv_id())
end

core.register_action("hook", { "http-res" }, hook)

My biggest problem is that there is no Content-length header so I don't know when I've processed all the information nor when to finish. Also, I've been unable to make get and set methods to work as every single time I call get I get the exact same information.

This is the HAProxy's configuration:

backend my-backend
  balance roundrobin
  http-response lua.hook
  server server_1 192.168.1.3:80 check

What is the correct way to process all the information before killing the backend server?

1

1 Answers

0
votes

When you use the forward function in "txn.res:forward(in_len)" you're moving the data from the input part of the http-response buffer to the output one.
Next you use the yield which will hands processing back to HAProxy and that is when the problem occurs. HAProxy was not able to analyze the headers (they were moved directly to the output buffer) and will consider the response invalid.
So I think you're always receiving only the first buffer before HAProxy

If you change the script and use it in a TCP context, HAProxy won't have to check if the HTTP response is valid and it will work correctly. In TCP context you're script can even be simplified to look like this:

function hook(txn) 
    local in_len = txn.res:get_in_len() 
    while in_len > 0 do 
            core.yield() 
            in_len = txn.res:get_in_len() 
    end 
    os.execute("docker rm -f server_" .. txn.sf:srv_id())
end 
core.register_action("hook", { "tcp-res" }, hook) 

Also you need to know that it is not a good idea to use os.execute(), because it will block HAProxy until the execution is done. More about it here in the "Non Blocking design" section. So it is better to take other choices like using an API to send an action to the container.