Hello Lucas,
On Thu, Dec 26, 2024 at 05:44:29PM +0000, Lucas Rolff wrote:
> Hello,
>
> I'm looking into doing some normalization of headers in haproxy to improve
> upstream cache-hit ratio.
> Basically I have a set of Apache Traffic Server instances upstream, which
> uses the Accept header for vary cache, but obviously since there's a huge
> amount of various Accept headers that browsers or HTTP clients send, it
> results in fairly bad hit ratios.
>
> Therefore I'd like to normalize the accept headers to something relatively
> simple.
>
> The goal is to do something depending like, if the extension requested is
> jpeg, jpg, png, gif, webp, then normalize the Accept header such as:
>
> If Accept header contains image/webp AND image/avif == Set Accept
> image/avif,image/webp
> If Accept header contains image/webp AND NOT image/avif == Set Accept
> image/webp
> If Accept header contains image/avif AND NOT image/webp == Set Accept
> image/avif
>
> Do anyone have a recommendation how to reach this goal easily in haproxy? In
> nginx for example, one can use a map:
> map $http_accept $img_suffix {
> default "none";
> "~*avif" "avif";
> "~*webp" "webp";
> }
>
> And then one can set the Accept header using $img_suffix result. Can one do
> something similar in haproxy?
I'd do it using variables for easier setup, probably something like:
http-request set-var(req.accept) str("image/avif,image/webp") if {
hdr(accept) -m sub image/webp } && { hdr(accept) -m sub image/avif }
http-request set-var(req.accept,ifempty) str("image/avif") if { hdr(accept)
-m sub image/avif }
http-request set-var(req.accept,ifempty) str("image/webp") if { hdr(accept)
-m sub image/webp }
http-request set-header accept var(req.accept)
I even think we could do it simpler based on your description, which consists
in adding each optional field if the string is present in Accept:
http-request set-var(req.accept)
'var(req.accept),add_item(",",,"image/avif")' if hdr(accept) -m sub image/avif
http-request set-var(req.accept)
'var(req.accept),add_item(",",,"image/webp")' if hdr(accept) -m sub image/webp
http-request set-header accept var(req.accept)
If only one matches, it will be alone. If the two match, they will appear
concatenated with a comma. You can repeat the operation as much as you
want with other tokens if needed. This is also cheaper. It would work as
well for accept-encoding and could be quite effective. This could be added
to the doc as a concrete example.
Hoping this helps,
Willy