Reputation: 733
I am writing a small website and for every page, I am putting a server name to its header:
func httpSignUp(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Server", SERVER_NAME)
}
I am wondering if there's a way that I can set http.ResponseWriter's default server name, so I don't have to use the same line over and over?
Upvotes: 4
Views: 2224
Reputation: 10862
"Prefer composition to inheritance" - Gang of 4
Inheritance simply wasn't designed into Golang in the first place. ;)
If you are looking for detailed explanations on the why part, I believed this has been answered on SO, hence I would just point you to it: Embedding instead of inheritance in Go.
Well, you can actually achieve the same result with adapter design pattern, which enables you to extend functionality from a built-in library, and to me, its way more flexible than inheritance.
func adapter(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", SERVER_NAME)
h.ServeHTTP(w, r)
})
}
Or pass in serverName
as parameter:
func adapter(h http.Handler, serverName string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
h.ServeHTTP(w, r)
})
}
Finally, you have the flexibility to choose which handler(s) to be 'inherited':
http.Handle("/path", adapter(your_handler))
Or if its meant for every handlers, just 'inherit' to the root-handler:
http.ListenAndServe(port, adapter(root_Handler))
Upvotes: 3
Reputation: 121169
Create a wrapper to set the header:
func wrap(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (
w.Header().Set("Server", SERVER_NAME)
h.ServeHTTP(w, r)
})
}
Wrap individual handlers
http.Handle("/path", wrap(aHandler)(
http.Handle("/another/path", wrap(anotherHandler))
or the root handler passed to ListenAndServe:
log.Fatal(http.ListenAndServe(addr, wrap(rootHandler))
Upvotes: 11
Reputation: 1839
The http.ResponseWriter
is an interface
, not a struct
. So, You cannot extend it directly. You need to extend the internal struct
. But it is not idiomatic way to solve this problem.
One approach you can take is to use middleware
. middleware
is just a piece of code which will be executed before your main request handler, and can be used perform some common tasks.
For example, to write the same thing using middleware
approach:
func injectServerHeader(handler http.Handler, serverName string) http.Handler {
ourFunc := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
handler.ServeHTTP(w, r)
}
return http.HandlerFunc(ourFunc)
}
This way, you wrap your actual http handler with middleware. So, you won't have to write same code over and over again.
For example:
http.Handle("/some-path", injectServerHeader(aHandler))
Upvotes: 3