[ 
https://issues.apache.org/jira/browse/YUNIKORN-3341?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated YUNIKORN-3341:
-------------------------------------
    Labels: pull-request-available  (was: )

> gzip middleware double-compresses responses that handlers already encoded
> -------------------------------------------------------------------------
>
>                 Key: YUNIKORN-3341
>                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3341
>             Project: Apache YuniKorn
>          Issue Type: Bug
>    Affects Versions: 1.9.0
>            Reporter: Ilia Lazebnik
>            Priority: Major
>              Labels: pull-request-available
>
> The gzip middleware on the REST router compresses any response whose buffered 
> body exceeds \{{minCompressionSize}}, without checking whether the wrapped 
> handler had already encoded the body itself.
> {\{/ws/v1/metrics}} is served by \{{promhttp.Handler()}}, which performs its 
> own gzip content negotiation: when the client sends \{{Accept-Encoding: 
> gzip}} it compresses the payload and sets \{{Content-Encoding: gzip}}. The 
> middleware then sees the same \{{Accept-Encoding}}, buffers promhttp's 
> already-gzipped bytes, finds them over the threshold, and compresses a second 
> time. \{{switchToGzip}} uses \{{Header().Set}}, so the response still 
> advertises a single \{{Content-Encoding: gzip}} while carrying a doubly 
> encoded body.
> Clients decode once and get gzip framing instead of the payload. For 
> Prometheus this means every scrape of \{{/ws/v1/metrics}} fails to parse and 
> the target is marked down, so scheduler metrics are lost entirely for any 
> scraper that advertises gzip support — which is the default.
> Reproduced against a running 1.9.0 scheduler:
> {code}
> $ curl -s -D- -o body.bin http://scheduler:9080/ws/v1/metrics
> 200 OK, 69714 bytes, "# HELP go_gc_duration_seconds ..."
> $ curl -s -D- -o body.gz -H 'Accept-Encoding: gzip' 
> http://scheduler:9080/ws/v1/metrics
> 200 OK, Content-Encoding: gzip, 8839 bytes
> $ gunzip -c body.gz | file -
> /dev/stdin: gzip compressed data          # still gzip after one decode
> $ gunzip -c body.gz | gunzip -c | head -1
> # HELP go_gc_duration_seconds ...         # payload only after two
> {code}
> This is a regression in 1.9.0: \{{pkg/webservice/gzip.go}} is new in that 
> release and \{{StartWebApp}} changed from \{{Handler: router}} to \{{Handler: 
> compressResponse(router)}}. The route itself and port 9080 are unchanged from 
> 1.8.0.
> *Proposed fix*
> Treat a \{{Content-Encoding}} set by the handler as a signal that the body is 
> already encoded, and pass the response through untouched. Metrics responses 
> stay compressed — promhttp still gzips them, just once — and handlers that do 
> not set \{{Content-Encoding}} are unaffected.
> Fixing \{{getMetrics}} alone (via \{{promhttp.HandlerOpts{DisableCompression: 
> true}}}) would patch only the one endpoint that self-encodes today; the 
> middleware would still corrupt any future handler that does the same.
> PR: https://github.com/apache/yunikorn-core/pull/1115



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to