prepareRequest clones req so that it can be safely modified without changing the original request or introducing data races. It then modifies it so that it is ready to be proxied, except for directing to a specific upstream. This method adjusts headers and other relevant properties of the cloned req
(req *http.Request, repl *caddy.Replacer)
| 760 | // proxying) regardless of proxy retries. This assumes that no mutations |
| 761 | // of the cloned request are performed by h during or after proxying. |
| 762 | func (h Handler) prepareRequest(req *http.Request, repl *caddy.Replacer) (*http.Request, error) { |
| 763 | req = cloneRequest(req) |
| 764 | |
| 765 | // if enabled, perform rewrites on the cloned request; if |
| 766 | // the method is GET or HEAD, prevent the request body |
| 767 | // from being copied to the upstream |
| 768 | if h.Rewrite != nil { |
| 769 | changed := h.Rewrite.Rewrite(req, repl) |
| 770 | if changed && (h.Rewrite.Method == "GET" || h.Rewrite.Method == "HEAD") { |
| 771 | req.ContentLength = 0 |
| 772 | req.Body = nil |
| 773 | } |
| 774 | } |
| 775 | |
| 776 | // if enabled, buffer client request; this should only be |
| 777 | // enabled if the upstream requires it and does not work |
| 778 | // with "slow clients" (gunicorn, etc.) - this obviously |
| 779 | // has a perf overhead and makes the proxy at risk of |
| 780 | // exhausting memory and more susceptible to slowloris |
| 781 | // attacks, so it is strongly recommended to only use this |
| 782 | // feature if absolutely required, if read timeouts are |
| 783 | // set, and if body size is limited |
| 784 | if h.RequestBuffers != 0 && req.Body != nil { |
| 785 | var readBytes int64 |
| 786 | req.Body, readBytes = h.bufferedBody(req.Body, h.RequestBuffers) |
| 787 | // set Content-Length when body is fully buffered |
| 788 | if b, ok := req.Body.(bodyReadCloser); ok && b.body == nil { |
| 789 | req.ContentLength = readBytes |
| 790 | req.Header.Set("Content-Length", strconv.FormatInt(req.ContentLength, 10)) |
| 791 | } |
| 792 | } |
| 793 | |
| 794 | if req.ContentLength == 0 { |
| 795 | req.Body = nil // Issue golang/go#16036: nil Body for http.Transport retries |
| 796 | } |
| 797 | |
| 798 | req.Close = false |
| 799 | |
| 800 | // if User-Agent is not set by client, then explicitly |
| 801 | // disable it so it's not set to default value by std lib |
| 802 | if _, ok := req.Header["User-Agent"]; !ok { |
| 803 | req.Header.Set("User-Agent", "") |
| 804 | } |
| 805 | |
| 806 | // Indicate if request has been conveyed in early data. |
| 807 | // RFC 8470: "An intermediary that forwards a request prior to the |
| 808 | // completion of the TLS handshake with its client MUST send it with |
| 809 | // the Early-Data header field set to “1” (i.e., it adds it if not |
| 810 | // present in the request). An intermediary MUST use the Early-Data |
| 811 | // header field if the request might have been subject to a replay and |
| 812 | // might already have been forwarded by it or another instance |
| 813 | // (see Section 6.2)." |
| 814 | if req.TLS != nil && !req.TLS.HandshakeComplete { |
| 815 | req.Header.Set("Early-Data", "1") |
| 816 | } |
| 817 | |
| 818 | reqUpgradeType := upgradeType(req.Header) |
| 819 | removeConnectionHeaders(req.Header) |
no test coverage detected