I want to setup a redirect map similar to this https://stackoverflow.com/questions/23001799/how-do-i-used-the-map-feature-in-haproxy-to-build-massive-redirect-tables-1-5
The difference is I want to use http-response
instead of http-request
. The reason being is because I want to redirect only when backend server returns 404.
This is my config
http-response redirect location %[capture.req.uri,regsub(\?(.*),),map(/etc/haproxy/redirects.map)] code 301 if { status 404 } { capture.req.uri,regsub(\?(.*),),map(/etc/haproxy/redirects.map) -m found }
I tried to use regsub
to remove query params from capture.req.uri
. But, I get this error when restarting HAProxy.
[ALERT] 280/171612 (6176) : parsing [/etc/haproxy/haproxy.cfg:87] : error detected in proxy 'http' while parsing 'http-response redirect' rule : error in condition: invalid arg 2 in conv method 'regsub' : missing arguments (got 1/2), type 'string' expected in ACL expression 'capture.req.uri,regsub(\?(.*),),map(/etc/haproxy/redirects.map)'.
[ALERT] 280/171612 (6176) : Error(s) found in configuration file : /etc/haproxy/haproxy.cfg
Errors found in configuration file, check it with 'haproxy check'.
Is there a way to get the URL without query params ? I tried to use path
instead of capture.req.uri
but HAProxy won't start.
This is my config using path
http-response redirect location %[path,map(/etc/haproxy/redirects.map)] code 303 if { status 404 } { path,map(/etc/haproxy/redirects.map) -m found }
And this is the warning
[WARNING] 283/090721 (2875) : parsing [/etc/haproxy/haproxy.cfg:88] : 'redirect' : sample fetch <path,map(/etc/haproxy/redirects.map)> may not be reliably used here because it needs 'HTTP request headers' which is not available here.
[WARNING] 283/090721 (2875) : parsing [/etc/haproxy/haproxy.cfg:88] : anonymous acl will never match because it uses keyword 'path' which is incompatible with 'backend http-response header rule'
Best Answer
The original issue was a problem with
regsub(\?(.*),)
, which caused a problem because the theregsub
converter is limited to expressions the configuration parser can handle -- and parentheses aren't usable because the parser sees the)
as closingregsub()
with too few arguments. (For literals, you can use\\xnn
hex-escapes to work around parser limitations, but that wouldn't work here.)regsub
was being used because this redirect is being triggered during response processingif { status 404 }
, and thepath
fetch is not available by that stage of processing -- HAProxy frees the buffers used to by the request once it is sent to a server.However, HAProxy 1.6 also introduces user variables that can be used to carry data across from the request side if used in transaction (
txn
) scope.During request processing, stash the contents of the
path
fetch in a transaction-scoped variable called (coincidentally)path
.Then, it can be accessed during response processing.
The following is shown on multiple lines for clarity but must be on a single line of configuration.
This -- if the response status code is 404 -- fetches the value back out of the variable and checks to see if it has a value in the map file. If so, that value is used for the redirect.