reverseProxy performs a round-trip to the given backend and processes the response with the client. (This method is mostly the beginning of what was borrowed from the net/http/httputil package in the Go standard library which was used as the foundation.)
(rw http.ResponseWriter, req *http.Request, origReq *http.Request, repl *caddy.Replacer, di DialInfo, next caddyhttp.Handler)
| 988 | // (This method is mostly the beginning of what was borrowed from the net/http/httputil package in the |
| 989 | // Go standard library which was used as the foundation.) |
| 990 | func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origReq *http.Request, repl *caddy.Replacer, di DialInfo, next caddyhttp.Handler) error { |
| 991 | _ = di.Upstream.Host.countRequest(1) |
| 992 | |
| 993 | // Increment the in-flight request count |
| 994 | incInFlightRequest(di.Address) |
| 995 | |
| 996 | //nolint:errcheck |
| 997 | defer func() { |
| 998 | di.Upstream.Host.countRequest(-1) |
| 999 | // Decrement the in-flight request count |
| 1000 | decInFlightRequest(di.Address) |
| 1001 | }() |
| 1002 | |
| 1003 | // point the request to this upstream |
| 1004 | h.directRequest(req, di) |
| 1005 | |
| 1006 | server := req.Context().Value(caddyhttp.ServerCtxKey).(*caddyhttp.Server) |
| 1007 | shouldLogCredentials := server.Logs != nil && server.Logs.ShouldLogCredentials |
| 1008 | |
| 1009 | // Forward 1xx status codes, backported from https://github.com/golang/go/pull/53164 |
| 1010 | var ( |
| 1011 | roundTripMutex sync.Mutex |
| 1012 | roundTripDone bool |
| 1013 | ) |
| 1014 | trace := &httptrace.ClientTrace{ |
| 1015 | Got1xxResponse: func(code int, header textproto.MIMEHeader) error { |
| 1016 | roundTripMutex.Lock() |
| 1017 | defer roundTripMutex.Unlock() |
| 1018 | if roundTripDone { |
| 1019 | // If RoundTrip has returned, don't try to further modify |
| 1020 | // the ResponseWriter's header map. |
| 1021 | return nil |
| 1022 | } |
| 1023 | h := rw.Header() |
| 1024 | copyHeader(h, http.Header(header)) |
| 1025 | rw.WriteHeader(code) |
| 1026 | |
| 1027 | // Clear headers coming from the backend |
| 1028 | // (it's not automatically done by ResponseWriter.WriteHeader() for 1xx responses) |
| 1029 | clear(h) |
| 1030 | |
| 1031 | return nil |
| 1032 | }, |
| 1033 | } |
| 1034 | req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) |
| 1035 | |
| 1036 | // do the round-trip |
| 1037 | start := time.Now() |
| 1038 | res, err := h.Transport.RoundTrip(req) |
| 1039 | duration := time.Since(start) |
| 1040 | |
| 1041 | // record that the round trip is done for the 1xx response handler |
| 1042 | roundTripMutex.Lock() |
| 1043 | roundTripDone = true |
| 1044 | roundTripMutex.Unlock() |
| 1045 | |
| 1046 | // emit debug log with values we know are safe, |
| 1047 | // or if there is no error, emit fuller log entry |
no test coverage detected