How to Make HA Proxy to Follow Redirects by Itself?
Asked Answered
A

2

5

I have java client which talks to 3rd party service through HA Proxy. 3rd party service was recently changed, so now it is returning 302(Moved Temporarily) instead of 200(Ok) which causes failure on my java client cause it expects 200 with actual response. For a number of reasons I want to avoid any code changes to the java client.

So, here is the question: Is there a way to make HA Proxy to follow redirects by itself and only return result(not 3xx http code) to the client?

One more thing to mention: I access HA Proxy via http, HA proxy accesses 3rd party resource via https, and returns 302 with location on https. Location varies, so configure HA Proxy to the new location is not an option.

HA Proxy version: HA-Proxy version 1.7.5 2017/04/03

OS: CentOS Linux release 7.2.1511 (Core)

Archduchess answered 13/6, 2018 at 18:50 Comment(0)
B
10

You can use this

$ haproxy -v
Nuster version 1.8.8.2.2
Copyright (C) 2017-2018, Jiang Wenyuan, <koubunen AT gmail DOT com >

HA-Proxy version 1.8.8.2 2018/05/29
Copyright 2000-2018 Willy Tarreau <[email protected]>

haproxy.conf

global
    debug
    lua-load handle_redirect.lua

frontend web1
    bind *:8080
    mode http

    default_backend app1

backend app1
    mode http

    http-response lua.handle_redirect if { status eq 301 }

    server s1 127.0.0.1:9000

handle_redirect.lua

http = require("http")

core.register_action("handle_redirect", {"http-res"}, function(txn)

  local hdr = txn.http:res_get_headers()
  if hdr["location"] == nil then
    return nil
  end


  local r, msg = http.get{
    url = hdr["location"][0]
  }

  if r == nil then
    return msg
  end

  local res = "HTTP/1.1 " .. r.status_code .. " " .. r.reason .. "\r\n"
  for k, v in pairs(r.headers) do
    res = res .. k .. ": " .. v .. "\r\n"
  end
  res = res .. "\r\n"
  res = res .. r.content


  txn.res:set(res)
  txn.done(txn)

end)

Download http.lua from https://github.com/haproxytech/haproxy-lua-http/blob/master/http.lua

haproxy -f haproxy.conf
Basting answered 15/6, 2018 at 9:0 Comment(4)
Thanks for you reply! I will try and come back to you.Archduchess
One thing, how can I add it to haproxy? I have haproxy here /usr/local/sbin/haproxy. Do I need to copy http.lua to the same location and create handle_redirect.lua file there?Archduchess
you can put in the same dir with haproxy.conf, also make sure haproxy have lua enabled by haproxy -vv, otherwise you need to build haproxy with lua support. also you might need to tweak the lua file in case the response is bigger than 16KBasting
http.lua also requires the json module which can be installed with lua-json in Ubuntu 20.04.Nominee
U
1

It seems like you are trying to solve the wrong problem.

It sounds like the site is returning 302 because you are not using HTTPS. So, configure the proxy to use HTTPS.

server foo foo.example.com:443 ssl verify none

You don't have to access the proxy using HTTPS, but the proxy needs to make the outbound request using HTTPS.

Additionally, HAProxy doesn't do what you are asking about. Responses can be modified as they are being returned, but you cannot force the proxy to follow a redirect.

Uxorial answered 13/6, 2018 at 23:51 Comment(7)
Thanks for your reply! Java client uses http to contact proxy, proxy uses https to contact 3rd party service, but 3rd party service is in fact return 302 to another url, so, as I understand, proxy can't handle redirects by itself.Archduchess
If the 3rd party service is returning a redirect, and the location is always the same, just configure the proxy to use the new location.Uxorial
No, location is not the same.Archduchess
What, it changes with each request?Uxorial
Location urls are determined based on user (user in this case is user of my java client and this 3rd party service as well), so these urls will be in different subdomains based on datacenter in which this user exists for this 3rd party service. Btw, I've updated the question with what we discussed here to avoid confusion.Archduchess
HAProxy is not a viable solution, here. This is outside its intended use cases. Additionally, this seems like a messy design on the part of the third party service, putting the burden on you instead of handling this themselves. They could give you a location to use (for that user) next time, while still servicing yout request this time.Uxorial
Thanks for your help! I can figure out urls for different users, but I wanted to avoid code changes to my java client. Seems like code change is the only option I have.Archduchess

© 2022 - 2024 — McMap. All rights reserved.