How to set http.ResponseWriter Content-Type header globally for all API endpoints?
Asked Answered
G

1

41

I am new to Go and I'm building a simple API with it now:

package main

import (
    "encoding/json"
    "fmt"
    "github.com/gorilla/mux"
    "github.com/gorilla/handlers"
    "log"
    "net/http"
)

func main() {
    port := ":3000"
    var router = mux.NewRouter()
    router.HandleFunc("/m/{msg}", handleMessage).Methods("GET")
    router.HandleFunc("/n/{num}", handleNumber).Methods("GET")

    headersOk := handlers.AllowedHeaders([]string{"Authorization"})
    originsOk := handlers.AllowedOrigins([]string{"*"})
    methodsOk := handlers.AllowedMethods([]string{"GET", "POST", "OPTIONS"})

    fmt.Printf("Server is running at http://localhost%s\n", port)
    log.Fatal(http.ListenAndServe(port, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
}

func handleMessage(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    message := vars["msg"]
    response := map[string]string{"message": message}
    w.Header().Set("Content-Type", "application/json") // this
    json.NewEncoder(w).Encode(response)
}

func handleNumber(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    number := vars["num"]
    response := map[string]string{"number": number}
    w.Header().Set("Content-Type", "application/json") // and this
    json.NewEncoder(w).Encode(response)
}

I feel like it's not clean to keep repeating w.Header().Set("Content-Type", "application/json") line in every API function that I have.

So my question here is, does it possible to set that http.ResponseWriter Content-Type header globally for all API functions that I have?

Glassware answered 21/7, 2018 at 12:50 Comment(2)
github.com/gorilla/mux/blob/master/README.md#middlewareBeltran
Thank you @Peter.Glassware
A
92

You can define middleware for mux router, here is an example:

func main() {
    port := ":3000"
    var router = mux.NewRouter()
    router.Use(commonMiddleware)

    router.HandleFunc("/m/{msg}", handleMessage).Methods("GET")
    router.HandleFunc("/n/{num}", handleNumber).Methods("GET")
    // rest of code goes here
}

func commonMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Add("Content-Type", "application/json")
        next.ServeHTTP(w, r)
    })
}

Read more in the documentation

Appalachia answered 21/7, 2018 at 12:59 Comment(3)
I'm confused about whether it's kosher to write to the ResponseWriter here. From the current docs: "Middlewares should write to ResponseWriter if they are going to terminate the request, and they should not write to ResponseWriter if they are not going to terminate it."Accumulator
It doesnt write header. Only WriteHeader method does.Appalachia
ah! That explains it. Thanks for the clarification and quick reply.Accumulator

© 2022 - 2024 — McMap. All rights reserved.