init should be called before we write a response, if rw.buf has contents.
()
| 444 | |
| 445 | // init should be called before we write a response, if rw.buf has contents. |
| 446 | func (rw *responseWriter) init() { |
| 447 | // Don't initialize encoder for error responses |
| 448 | // This prevents response corruption when handle_errors is used |
| 449 | if rw.disabled { |
| 450 | return |
| 451 | } |
| 452 | |
| 453 | hdr := rw.Header() |
| 454 | |
| 455 | if hdr.Get("Content-Encoding") == "" && isEncodeAllowed(hdr) && |
| 456 | rw.config.Match(rw) { |
| 457 | rw.w = rw.config.writerPools[rw.encodingName].Get().(Encoder) |
| 458 | rw.w.Reset(rw.ResponseWriter) |
| 459 | hdr.Del("Content-Length") // https://github.com/golang/go/issues/14975 |
| 460 | hdr.Set("Content-Encoding", rw.encodingName) |
| 461 | if !hasVaryValue(hdr, "Accept-Encoding") { |
| 462 | hdr.Add("Vary", "Accept-Encoding") |
| 463 | } |
| 464 | hdr.Del("Accept-Ranges") // we don't know ranges for dynamically-encoded content |
| 465 | |
| 466 | // strong ETags need to be distinct depending on the encoding ("selected representation") |
| 467 | // see RFC 9110 section 8.8.3.3: |
| 468 | // https://www.rfc-editor.org/rfc/rfc9110.html#name-example-entity-tags-varying |
| 469 | // I don't know a great way to do this... how about appending? That's a neat trick! |
| 470 | // (We have to strip the value we append from If-None-Match headers before |
| 471 | // sending subsequent requests back upstream, however, since upstream handlers |
| 472 | // don't know about our appending to their Etag since they've already done their work) |
| 473 | if etag := hdr.Get("Etag"); etag != "" && !strings.HasPrefix(etag, "W/") { |
| 474 | etag = fmt.Sprintf(`%s-%s"`, strings.TrimSuffix(etag, `"`), rw.encodingName) |
| 475 | hdr.Set("Etag", etag) |
| 476 | } |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | func hasVaryValue(hdr http.Header, target string) bool { |
| 481 | for _, vary := range hdr.Values("Vary") { |