Is there a way to do this? The only way to do this that I’ve been able to find is have multiple ACLs, and then combine them in a condition for an action. But that becomes very unwieldy if there are multiple cases for the ACL and/or if there are multiple actions that use the ACL (possibly combined with other ACLs or inline conditions).
That can get difficult to maintain, when you have several actions for the same condition (for example setting multiple headers). If the condition changes, you then have to change it in several places instead of just one.
Right, with inline/anonymous ACL’s you’d need to update every single statement on changes.
With named ACLs, imho mixing different match statements into a single ACL is actually more confusing then the alternative. I’d argue that a configuration like this is more readable, especially if used multiple times:
A “meta” ACL that can combine multiple ACL’s (just like a condition today) would probably be a construct that it’s best suited for this. But I’m not sure if this is worth the effort.
I should also note that this particular example could also be improved if there was a single fetch to get the domain and path together without the query string. But afaik, that isn’t possible either. And there are other cases where this would be useful, matching on both the domain and path is just the most common that I’ve run into.
@j_bourdeau I’m aware of that. The problem is that I end up with actions like:
http-request set-header My-Header1 value1 if ACL_domain1 ACL_path1 or ACL_domain2 ACL_path2 or ACL_domain3 or ACL_domain3 or ACL_domain3 ACL_path4 or ...
possibly with the condition repeated multiple times to perform multiple actions (say, setting multiple headers if a condition applies), and then if I need to add a new url to that condition, I have to make the change in several places.
looks like you are trying to do the web site’s job at the proxy level. What is supposed to be done by the Web application should be done by that application and not compensated for by a proxy.
Also, the example you gave is again pretty basic. Either give the full extent of the problem so we can work it with you, or instead, we can only provide you with the same basic solutions.
From here, I guess your logic is wrong / over complicated. You should re-design your logic and I expect a simpler way will emerge from that.
Or as another solution, you could cascade multiple processing stages to compensate for your messy logic :
HAproxy receives the request on a first socket and routes the request based on a first criteria like domain. Requests for Domain1 are sent to local port 1, Domain2 is sent to port 2, Domain 3 is sent to port 3, each of them with the required header for the corresponding domain (Header Dx).
On the FrontEnd listening on Port 1, you don’t need to test for Domain1 anymore because you know it is set. It has been sorted already. So all you need now is to work based on path. Path A sent to port A, path B sent to port B, … again adding the proper Header Px.
On that third FrontEnd, do whatever you need and keep going as long as you need.
At the end of the maze, all your backends may go to the same place or to different places, as you need. But each query will have been modified according to the criteria from its corresponding HAProxy path routing.
acl ACL_sample hdr(Host) special-domain
acl ACL_sample base domain1/path1
acl ACL_sample base domain2/path2
acl ACL_sample base domain3/path3
acl ACL_sample base domain4/path4
Here is a specific example, that base doesn’t solve (but only benefits from AND in acls a little):
We have a MATCH_allow-iframed ACL that has a whitelist of paths that are allowed to be iframed, and then the following rules:
http-response del-header X-Frame-Options
http-response set-header X-Frame-Options SAMEORIGIN if !MATCH_allow-iframed
But then we wanted to add rules that set X-Frame-Options for a certain path only if it doesn’t come from a certain referrer. In this case it is a single action that uses the ACL, so we could write something like:
http-response set-header X-Frame-Options SAMEORIGIN unless MATCH_allow-iframed or MATCH_path1 MATCH_referer1 or MATCH_path2 MATCH_referer2 or ...
But that leads to a very long condition. We eventually found a better solution, but it made me wonder if there was a better way to do something like that, and if not, why not.