Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set http headers for multiple handlers in go

Tags:

go

I'm trying to set an http header for multiple handlers. My first thought was to make a custom write function that would set the header before writing the response like the code sample at the bottom.

However, when I pass a pointer to the http.ResponseWriter and try to access it from my function it tells me that "type *http.ResponseWriter has no Header method".

What is the best way to set headers for multiple handlers, and also why isn't the pointer working the way I want it to?

func HelloServer(w http.ResponseWriter, req *http.Request) {
    type Message struct {
        Name string
        Body string
        Time int64
    }

    m := Message{"Alice", "Hello", 1294706395881547000}

    b, _ := json.Marshal(m)
    WriteJSON(&w, b)
}

func WriteJSON(wr *http.ResponseWriter, rawJSON []byte) {
    *wr.Header().Set("Content-Type", "application/json")

    io.WriteString(*wr, string(rawJSON))
}

func main() {
    http.HandleFunc("/json", HelloServer)

    err := http.ListenAndServe(":9000", nil)
    if err != nil {
    log.Fatal("ListenAndServer: ", err)
    }
}
like image 625
Seth Archer Brown Avatar asked Mar 23 '23 04:03

Seth Archer Brown


2 Answers

I'm not sure about the multiple handlers thing, but I do know why the code you wrote is failing. The key is that the line:

*wr.Header().Set("Content-Type", "application/json")

is being interpreted, because of operator precedence, as:

*(wr.Header().Set("Content-Type", "application/json"))

Since wr has the type *http.ResponseWriter, which is a pointer to and interface, rather than the interface itself, this won't work. I assume that you knew that, which is why you did *wr. I assume what you meant to imply to the compiler is:

(*wr).Header().Set("Content-Type", "application/json")

If I'm not mistaken, that should compile and behave properly.

like image 154
joshlf Avatar answered Mar 25 '23 19:03

joshlf


You don't need to use *wr as it already references a pointer.

wr.Header().Set("Content-Type", "application/json") should be sufficient.

If you want to set "global" headers for every request, you can create a function that satisfies http.HandleFunc (go.auth has a good example) and then wrap your handlers like so:

http.HandleFunc("/hello", Defaults(helloHandler))

Also take a look at the net/http documentation, which has further examples.

like image 33
elithrar Avatar answered Mar 25 '23 19:03

elithrar