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