1

I'm trying to set a cookie based on a response header from within middleware used in a reverse proxy request.

Problem: I can only get the response header after next.ServerHTTP(w, r) and I can only set a cookie before it. (So it seems)

See the comments in the handler method I'm using as middleware. (I've abbreviated this code for this question)

package main

import (

    "github.com/gorilla/mux"
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
)

func setCookie(w http.ResponseWriter, name string, value string) {
    ...
    http.SetCookie(w, &cookie)
}

func handler(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        // setCookie() works here
        // but I cannot access w.Header().Get("X-FOO")

        next.ServeHTTP(w, r)

        // I can access w.Header().Get("X-FOO") here
        // but setCookie() does not cookie the user's browser

        // If I could do it all in one place, this is what I would do:
        if r.Method == "POST" && r.URL.String() == "/login" {
            foo := w.Header().Get("X-FOO")
            setCookie(w, "MYAPPFOO", foo)

        }
    })
}

func main() {

    r := mux.NewRouter()
    r.Use(handler)
        proxy := httputil.NewSingleHostReverseProxy("https://baz.example.com/")
        r.PathPrefix("/").Handler(proxy)
        log.Fatal(http.ListenAndServe(":9001", r))
}

Is it possible to set a cookie based on a response header from the server?

If it's not clear, here's the desired workflow:

  • User requests http://example.com/foo/bar
  • Go app proxies to http://baz.example.com
  • baz.example.com sets a response header X-FOO
  • Go app modifies response by setting a MYAPPFOO cookie with the value of the X-FOO response header
  • The cookie is written to the user's browser
Coder1
  • 13,139
  • 15
  • 59
  • 89
  • 2
    There is a `ModifyResponse` hook in `proxy` which should be able to modify the response header before it gets forwarded to the client. – Steffen Ullrich Nov 09 '19 at 05:59
  • I've tested this successfully. If I can't achieve it with middleware (cleaner for my purposes), then I'll be going with `ModifyResponse`. Thanks! – Coder1 Nov 09 '19 at 07:43
  • What you're attempting will work fine, but you need to use your own `http.ResponseWriter` implementation, that doesn't send data to the client until after your modifications. – Jonathan Hall Nov 09 '19 at 08:20
  • @Flimzy thanks for the lead. I gave it a solid try but the question you referenced this as a duplicate of does not demonstrate how to set a cookie based on a response header within the middleware of a reverse proxy. I understand cookie management is just headers and middleware is a common pattern, but I am having no luck applying that question, or the blog post he linked, to my question. – Coder1 Nov 09 '19 at 12:42
  • @Coder1: Does [this](https://stackoverflow.com/q/12130582/13860) help with that part? – Jonathan Hall Nov 10 '19 at 08:55
  • @Flimzy your initial response helped move me forward. At my level of experience on this topic, I was not able to figure it out. With my issue closed here, I knew a little more of what I was looking for so [this](https://stackoverflow.com/questions/58779594/using-a-custom-http-responsewriter-to-write-cookies-based-on-the-response-from-a) question/answer helped me understand the detail. I was bummed my Q got closed here, but it ended up helping me ask a better question. Thank you here and on other questions. – Coder1 Nov 10 '19 at 15:20

0 Answers0