From aef8d4decceba3371d6722a81e17cd5f94162116 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Wed, 12 May 2021 16:19:08 -0400 Subject: reverseproxy: Set the headers in the replacer before `handle_response` (#4165) Turns out this was an oversight, we assumed we could use `{http.response.header.*}` but that doesn't work because those are grabbed from the response writer, and we haven't copied any headers into the response writer yet. So the fix is to set all the response headers into the replacer at a new namespace before running the handlers. This adds the `{http.reverse_proxy.header.*}` replacer. See https://caddy.community/t/empty-http-response-header-x-accel-redirect/12447 --- modules/caddyhttp/reverseproxy/reverseproxy.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'modules/caddyhttp/reverseproxy/reverseproxy.go') diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index ddb3ca9..671f42a 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -120,9 +120,10 @@ type Handler struct { // handler chain will not affect the health status of the // backend. // - // Two new placeholders are available in this handler chain: - // - `{http.reverse_proxy.status_code}` The status code - // - `{http.reverse_proxy.status_text}` The status text + // Three new placeholders are available in this handler chain: + // - `{http.reverse_proxy.status_code}` The status code from the response + // - `{http.reverse_proxy.status_text}` The status text from the response + // - `{http.reverse_proxy.header.*}` The headers from the response HandleResponse []caddyhttp.ResponseHandler `json:"handle_response,omitempty"` Transport http.RoundTripper `json:"-"` @@ -631,9 +632,17 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, repl * if len(rh.Routes) == 0 { continue } + res.Body.Close() + + // set up the replacer so that parts of the original response can be + // used for routing decisions + for field, value := range res.Header { + repl.Set("http.reverse_proxy.header."+field, strings.Join(value, ",")) + } repl.Set("http.reverse_proxy.status_code", res.StatusCode) repl.Set("http.reverse_proxy.status_text", res.Status) + h.logger.Debug("handling response", zap.Int("handler", i)) if routeErr := rh.Routes.Compile(next).ServeHTTP(rw, req); routeErr != nil { // wrap error in roundtripSucceeded so caller knows that -- cgit v1.2.3