I'm working on a project to switch between backends based on whether a URL path prefix is found in a map file. Straightforward enough.
In the runtime environment, the haproxy config is generated from a template and it is possible that a configured backend is not available despite being listed in the map file. What I'd like to do to write my config to try the preferred backend, fall back to a special backend if the preferred one is not available, and only then go to the default backend as a last resort. I found two prior mailing list threads on this topic: "try other backend when backlog is full or backend unavailable, but only in that case" https://www.mail-archive.com/[email protected]/msg07493.html "HAProxy - Try Multiple Backends Sequentially?" https://www.mail-archive.com/[email protected]/msg26057.html Example config for what I'd like to do: # Get the backend for the request path prefix http-request set-var(req.pref_backend) path,map_beg(path-prefix-backends.map) # If the variable was set, use it to choose the backend use_backend be_%[var(req.pref_backend)] if { var(req.pref_backend) -m found } # If the path prefix is in the map, but the backend isn't up, handle specially use_backend be_configured_path_broken if { var(req.pref_backend) -m found } # Last resort use the no_match backend for a generic error response default_backend no_match The problem is that if the first "use_backend" command resolves to a backend that does not exist, the "default_backend" is used. This is exactly as documented, so it's not a surprise, but I was vaguely hoping for something different :) "If <backend> is a log-format string instead, no check may be done at configuration time, so the backend name is resolved dynamically at run time. If the resulting backend name does not correspond to any valid backend, no other rule is evaluated, and the default_backend directive is applied instead." My first attempt to work around this limitation was to use "nbsrv" but it appears to accept only literal strings and not log-format strings? # Does not work for me: acl is_pref_backend_available nbsrv(%[var(req.pref_backend)]) gt 0 Proposal: New acl "backend_exists(string or log-format-string)" - returns a bool if a backend is defined at runtime. Augment acl "nbsrv(string)" to "nbsrv(string or log-format-string)" - returns an int count of healthy backends at runtime. Lua Escape Hatch It would appear that I could do this in Lua, following the example in this HAProxy Tech blog post: https://www.haproxy.com/blog/5-ways-to-extend-haproxy-with-lua/ The Lua option feels a little unfortunate because it would have to iterate of core.backends and do a string comparison for each backend to find the one that matches the map lookup, or finish iterating without finding a match - and so then set a variable to use the special fallback. So I do think it would be helpful to have an acl for this, since it is possible today to write a "use_backend" command that references a non-existent backend at runtime and I'd like to catch those cases. Thanks, Aaron

