I am trying to improve the user experience by having haproxy handle multiple redirects.
haproxy 2.8
lua 5.6
The initial request is identified by a leading A in the path, and if it starts with then then I want it to follow all the redirects starting with the URL I pull from a JSON service.
global
log 127.0.0.1 local2
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
chroot /var/lib/haproxy
maxconn 4000
lua-load /etc/haproxy/follow_redirects.lua
daemon
defaults
mode http
option httplog
log global
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend http_front
bind *:80
bind *:443 ssl crt /etc/haproxy/ssl
# Use the Lua script for initial requests starting with /A
http-request lua.follow_redirects if { path_beg /A }
default_backend web_backend
backend web_backend
option forwardfor
server webserver loadbalancer.com:443 ssl verify none
Then in the lua script I have this.
http = require("http")
core.register_service("follow_redirects", "http", function(applet)
local max_redirects = 2 -- You can change this to your preferred maximum number of redirects
local user_id = applet.path:sub(3) -- assuming the path starts with '/A'
local url = "http://backendsystem.com/find_user?user_id=" .. user_id
local headers = {}
local count = 0
local response, status_code, response_headers, status_line = http.request {
url = url,
sink = ltn12.sink.table(response.body),
}
-- Collecting initial request headers
for name, value in pairs(applet.headers) do
headers[name:lower()] = value[0]
end
while count < max_redirects do
-- Sending the request
local response, err = http.get({url = url, headers = headers})
if not response then
applet:set_status(500)
applet:add_header("Content-Type", "text/plain")
applet:start_response()
applet:send(err)
return
end
-- If the response is not a redirect, break the loop
if response.status ~= 301 and response.status ~= 302 then
break
end
-- Updating URL for the next request
url = response.headers["location"]
count = count + 1
end
-- Responding with the final fetched content or redirect
applet:set_status(response.status)
for k, v in pairs(response.headers) do
applet:add_header(k, v)
end
applet:start_response()
if response.body then
applet:send(response.body)
end
end)
It never completes the chain and gets to the last redirect. What am I doing wrong?
1 post - 1 participant