Wonderful, thank you Willy! I'll give it a try!

Wish you a lovely evening!

- Lucas Rolff

On 26 Dec 2024, at 19:01, Willy Tarreau <w...@1wt.eu> wrote:

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

Reply via email to