Map file no match when key contains space - escaping not working


Ladies and Gents
I’m trying to use a map file to make dynamic backend decisions based on user agent strings.
Problem is my user agent has spaces in it.
The mapfile works without spaces:

teststring dest_pool

and in the cfg:
acl has_http_useragent hdr(user-agent),map_str(/usr/local/haproxy/maps/webcenter_useragents.cfg) -m found
use_backend %[req.hdr(user-agent),map_str(/usr/local/haproxy/maps/webcenter_useragents.cfg)] if has_http_useragent

If I add and escape a space it doesn’t match anymore:

test\ string dest_pool

I get a NOSRV

Q1. Can I change the default delimiter for the k/v’s in a map ? I have not found a reference to that.
Q2. Is there any other way to deal with the spaces ?

Unfortunately, my user agent is “Studio Site Designer”

Thx for a great product


Ok here is one way, using regex

^test[[:space:]]string$ dest_pool

with map_reg does the trick but I don’t wanna use regex unless I absolutely have to.
It appears the default space delimiter in maps cannot be changed so regex with [[:space:]] appears to be the
only workaround I can think of.
Can anyone confirm that there is a non-regex method available ?


This is currently not possible, keys are not supposed to have spaces in them:

The file contains one key + value per line. Lines which start with ‘#’ are ignored, just like empty lines. Leading tabs and spaces are stripped. The key is then the first “word” (series of non-space/tabs characters), and the value is what follows this series of space/tab till the end of the line excluding trailing spaces/tabs.

So user-agent matching is not a good use-case for maps. Usually we would just match an ACL against a list, like:
acl valid-ua hdr(user-agent) -f exact-ua.lst

Meaning you’d specify an separate list for every backend, which may not be desirable when you have a lot of backends.

@thierry any opinion about how we could handle keys containing spaces in map files? A custom delimiter with a new map_ option or something like that?


Ahhh got it. Turns out I had actually overcomplicated this with maps where all values are the same backend so a list was really all I needed.
Yes this works but I’d argue that a use case exists for maps where you cannot control the key and it might contain whitespace.
A simple option to set a custom delimiter would do. Otherwise, there is always good old regex to the rescure but it’s expensive.