I'm trying to configure HAProxy to allow a specific set of HTTP methods to a specific set of paths, stored in a map.
For example, I have a haproxy map file which contains the following:
/api/read_method GET
/api/write_method POST
Given the above map, I would like to allow GET
requests starting with /api/read_method
(but no other methods), and POST
requests to paths starting /api/write_method
(but no GETs).
Based on the documentation, I have arrived at the following haproxy configuration:
listen main
# bind, doesn't really matter
bind *:443 ssl crt server.pem
# use path_beg to find the map entry starting with the path
# compare the request method with the returned map entry, case insensitively as astring
acl map_method method -i -m str %[path,map_beg(acl.map)]
http-request deny unless map_method
server app backend:80
This ACL never seems to match, the request is always denied, even when I test as follows:
curl -v https://localhost/api/read_method # do a GET to the path in the map
I have attempted to debug this using the following line, as a modification to the http-request deny
statement:
http-request return status 401 content-type text/plain lf-string "Denied, allowed method for %[path] is >(%[path,map_beg(acl.map)])< but method was >(%[method])<" unless url_method
This denies the request with a log-format message, which returns as follows:
Denied, allowed method for /api/read_method is >(GET)< but request method is >(GET)<
I don't understand why this condition isn't satisfying the ACL, the strings are identical and the comparison is done as a string (-m str
). The map is definitely returning the appropriate method (shown in the debug string), and if I swap the map lookup for a literal "GET
", the ACL passes correctly (but not when the same string is returned from the lookup).