HTTP handler function - go

I saw some http handler function declarations are varied.
Two of them I found are the standard function and the one returning anonymous function inside the handler.
For example:
Using standard way:
func helloworld(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World")
}
This the most straight way to declare a handler for an http api.
Another way is using anonym/closure function inside the handler function:
func helloworld2() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
fmt.Fprintln(w, "Hello World")
})
}
What are the differences and the benefit? When to use one of them? What's the best practice?

Pattern
func Middleware(next http.Handler) http.Handler{
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Do something
next.ServeHTTP(w, r)
})
}
often used to construct middleware chain like
http.Handle("/", middlewareOne(middlewareTwo(finalHandler)))

Returning an anonymous function is the only way to work with handlers that require additional arguments, by returning a closure. Example:
func fooHandler(db *someDatabase) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do something with `db` variable
}
}
Otherwise, there's typically no practical difference between the approaches. One may choose to use the anonymous function universally for consistency.

One of the most popular source of information about structure returning anonymous functions is a blog post from Mat Ryer How I write HTTP services after eight years
I sure it will be good to provide some quotes from his article here:
... handler functions don’t actually handle the requests, they return a function that does. This gives us a closure environment in which our handler can operate:
func (s *server) handleSomething() http.HandlerFunc {
thing := prepareThing()
return func(w http.ResponseWriter, r *http.Request) {
// use thing
}
}
The prepareThing is called only once, so you can use it to do one-time
per-handler initialisation, and then use the thing in the handler.
Also,
If an endpoint has its own request and response types, usually they’re only useful for that particular handler. If that’s the case, you can define them inside the function.
func (s *server) handleSomething() http.HandlerFunc {
// you have these handy structs always visible to your handler and eyes
// and invisible to code that don't use them
type request struct {
Name string
}
type response struct {
Greeting string `json:"greeting"`
}
return func(w http.ResponseWriter, r *http.Request) {
// decode into request struct
// validate
// call business-logic
// encode response from business-logic into response struct
}
}
In practice, writing RESTy APIs you have handler named after resource, e.g. you have /maps resource and appropriate handler struct mapsHandler with injected dependencies (repositories, services containing some business-logic, loggers) into it. But sometimes you will also need to pass an additional dependency exclusively per one handle and suddenly realized that handler has strict signature, so you should wrap it. Then you have something like this
// RESTy routes for "maps" resource
router.Route("/maps", func(r chi.Router) {
adHocDependency := newAdHocDependency(options)
r.Post("/", mapsHandler.handleCreateMap(adHocDependency))
})
making your ad hoc dependency visible to your handler.
Hope it helps!

Related

gorilla mux middleware: wrapping a handler

I need to wrap the GetAssetsCompute function inside a middleware
r.Handle("/api/v1/assets/ComputeBlade", GetAssetsCompute(assetService)).Methods("GET")
func GetAssetsCompute(assetService ServiceType) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// stuff here
})
}
but because middlewares take HTTP handlers as an argument and my function is not a handler, I can't.
I was thinking of doing something like this.
func GetAssetsCompute(assetService ServiceType) http.Handler {
return MyMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// stuff here
}))
}
func MyMiddleware(next http.Handler) http.Handler {
}
Is this correct? Or is there a better way to do this.
Also inside the middleware, I need to access the URL endpoint, do some processing and store this processed value and then again access that in the main handler. How can I do that?
EDIT: I want to apply this middleware to only a subset(>1) of endpoints I have. Not all
I also require the assetService variable used in GetAssetsCompute(assetService ServiceType) function in the handler. So, I need this closure too.
It seems you are trying to do 2 things. 1 - Apply a middleware to only some of your request handlers. 2 - Pass data from your middleware to your request handlers.
For the first one, I can think of three options. The first is what you are doing now, having a Middleware function in which you wrap your handler functions when you pass them to r.Handle. Pseudocode:
r.Handle("/path1", Mware(Handler1())).Methods("GET")
r.Handle("/path2", Mware(Handler2())).Methods("GET")
r.Handle("/path3-nomiddleware", Handler3()).Methods("GET")
The second thing you could do is to add code to your middleware to filter based on URI path and then register your middleware using r.Use. Pseudocode:
const mwarePaths []string = ...
func Mware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.RequestURI is in mwarePaths {
// do the middleware
}
}
}
r.Use(Mware)
Thirdly, you could put the code in a function which you call directly in your handlers and not register it like a middleware. Pseudocode:
func myUtil(w http.ResponseWriter, r *http.Request){ ... }
func GetAssetsCompute(assetService ServiceType) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
myUtil(w, r)
// stuff here
})
}
For the second thing - passing data from middleware to request handlers - here are some ideas.
First, if you go with the regular-function, no-middleware setup above, this problem disappears because anything you need in your handler can simply be a return value from your function.
If you do use a middleware, you can use the context library (also from gorilla) to tie variables to an http.Request instance for passing to your handler: http://www.gorillatoolkit.org/pkg/context . Using that looks like this:
import "github.com/gorilla/context"
func middleware(...) {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
context.Set(r, "myKey", "bar")
}
}
func handler(w http.ResponseWriter, r *http.Request) {
val, ok := context.GetOk(r, "myKey") // returns "bar", true
}
Which of these options you choose to use is up to you (you know your needs). But, as mentioned in the comments, a good rule of thumb would be that code which handles unrelated concerns to what your request handlers do can be middleware. Code which handles concerns that are directly related to what your request handlers are doing can go directly in the handlers.

Passing along data with request [duplicate]

I am designing my handlers to return a http.Handler. Here's the design of my handlers:
func Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
})
}
My middleware is designed to accept an http.Handler and then call the handler once the middleware has finished performing its operations. Here's the design of my middleware:
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Middleware operations
next.ServeHTTP(w, r)
})
}
Considering the design of my middleware and handlers, what is the proper way of passing information from the middleware to the handler? The information that I am trying to pass from my middleware to the handlers is a JSON web token parsed from the request body. If I do not pass the parsed JWT to the handler, then I will need to parse the JWT again in my handlers. Parsing the request body for a JWT in both the middleware and handler seems wasteful. Just in case this information is relevant, I am using the standard net/http library with gorilla mux.
Since you're already using Gorilla take a look at the context package.
(This is nice if you don't want to change your method signatures.)
import (
"github.com/gorilla/context"
)
...
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Middleware operations
// Parse body/get token.
context.Set(r, "token", token)
next.ServeHTTP(w, r)
})
}
...
func Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := context.Get(r, "token")
})
}
Update
The Gorilla context package is now in maintenance mode
per the repo:
Note gorilla/context, having been born well before context.Context existed, does not play well with the shallow copying of the request that http.Request.WithContext (added to net/http Go 1.7 onwards) performs.
Using gorilla/context may lead to memory leaks under those conditions, as the pointers to each http.Request become "islanded" and will not be cleaned up when the response is sent.
You should use the http.Request.Context() feature in Go 1.7.
The proper way to pass request scoped data would now be the context package in the standard library.
https://golang.org/pkg/context/
You can access it with request.Context on an http.Request.
A first approach, similar to the question, is in codemodus/chain by Daved.
Package chain aids the composition of Handler wrapper chains that carry request-scoped data.
It uses the notion of Context, coupled with a Context handler:
func ctxHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
// ...
if s, ok := getMyString(ctx); ok {
// s = "Send this down the line."
}
// ...
}
Another approach: You can have a look at "Custom Handlers and Avoiding Globals in Go Web Applications", by Matt Silverlock (elithrar). (full example here)
The idea is to define ServeHTTP on a type which include the relevant context.
// We've turned our original appHandler into a struct with two fields:
// - A function type similar to our original handler type (but that now takes an *appContext)
// - An embedded field of type *appContext
type appHandler struct {
*appContext
h func(*appContext, http.ResponseWriter, *http.Request) (int, error)
}
// Our ServeHTTP method is mostly the same, and also has the ability to
// access our *appContext's fields (templates, loggers, etc.) as well.
func (ah appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Updated to pass ah.appContext as a parameter to our handler type.
status, err := ah.h(ah.appContext, w, r)
if err != nil {
log.Printf("HTTP %d: %q", status, err)
switch status {
case http.StatusNotFound:
http.NotFound(w, r)
// And if we wanted a friendlier error page, we can
// now leverage our context instance - e.g.
// err := ah.renderTemplate(w, "http_404.tmpl", nil)
case http.StatusInternalServerError:
http.Error(w, http.StatusText(status), status)
default:
http.Error(w, http.StatusText(status), status)
}
}
}
In the appContext struct, you would put any data you want to pass around.

Add response header to every handler without repeating the same line

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?
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))
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))
"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))

How can I pass data from middleware to handlers?

I am designing my handlers to return a http.Handler. Here's the design of my handlers:
func Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
})
}
My middleware is designed to accept an http.Handler and then call the handler once the middleware has finished performing its operations. Here's the design of my middleware:
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Middleware operations
next.ServeHTTP(w, r)
})
}
Considering the design of my middleware and handlers, what is the proper way of passing information from the middleware to the handler? The information that I am trying to pass from my middleware to the handlers is a JSON web token parsed from the request body. If I do not pass the parsed JWT to the handler, then I will need to parse the JWT again in my handlers. Parsing the request body for a JWT in both the middleware and handler seems wasteful. Just in case this information is relevant, I am using the standard net/http library with gorilla mux.
Since you're already using Gorilla take a look at the context package.
(This is nice if you don't want to change your method signatures.)
import (
"github.com/gorilla/context"
)
...
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Middleware operations
// Parse body/get token.
context.Set(r, "token", token)
next.ServeHTTP(w, r)
})
}
...
func Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := context.Get(r, "token")
})
}
Update
The Gorilla context package is now in maintenance mode
per the repo:
Note gorilla/context, having been born well before context.Context existed, does not play well with the shallow copying of the request that http.Request.WithContext (added to net/http Go 1.7 onwards) performs.
Using gorilla/context may lead to memory leaks under those conditions, as the pointers to each http.Request become "islanded" and will not be cleaned up when the response is sent.
You should use the http.Request.Context() feature in Go 1.7.
The proper way to pass request scoped data would now be the context package in the standard library.
https://golang.org/pkg/context/
You can access it with request.Context on an http.Request.
A first approach, similar to the question, is in codemodus/chain by Daved.
Package chain aids the composition of Handler wrapper chains that carry request-scoped data.
It uses the notion of Context, coupled with a Context handler:
func ctxHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
// ...
if s, ok := getMyString(ctx); ok {
// s = "Send this down the line."
}
// ...
}
Another approach: You can have a look at "Custom Handlers and Avoiding Globals in Go Web Applications", by Matt Silverlock (elithrar). (full example here)
The idea is to define ServeHTTP on a type which include the relevant context.
// We've turned our original appHandler into a struct with two fields:
// - A function type similar to our original handler type (but that now takes an *appContext)
// - An embedded field of type *appContext
type appHandler struct {
*appContext
h func(*appContext, http.ResponseWriter, *http.Request) (int, error)
}
// Our ServeHTTP method is mostly the same, and also has the ability to
// access our *appContext's fields (templates, loggers, etc.) as well.
func (ah appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Updated to pass ah.appContext as a parameter to our handler type.
status, err := ah.h(ah.appContext, w, r)
if err != nil {
log.Printf("HTTP %d: %q", status, err)
switch status {
case http.StatusNotFound:
http.NotFound(w, r)
// And if we wanted a friendlier error page, we can
// now leverage our context instance - e.g.
// err := ah.renderTemplate(w, "http_404.tmpl", nil)
case http.StatusInternalServerError:
http.Error(w, http.StatusText(status), status)
default:
http.Error(w, http.StatusText(status), status)
}
}
}
In the appContext struct, you would put any data you want to pass around.

Organize routes and helpers

I am starting building a api in go(golang), but I have few questions...
So in my main function or init function(because I might use appengine) I was thinking in calling a function which will define all my routes using gorilla mux. Each pice of my application(post, comments etc...) will have its one package with its structures/methods/functions.
Questions:
Because I was thinking in defining the routes in one function, do I need to import in this file all my packages, to send the requests to the right handlers?
What about helper function, for example I would like to set content type of the response to be application/json for all the handlers where this is necessary, how I will be able to do that?
I'm not looking for frameworks, just some pointer about how can I overcome those questions in golang way.
If you define all of the routes in a single function, then the file containing this function will need to import the packages that implement the handlers. The only way to refer to a type or function in another package is to import the package.
Here's a helper for setting the content type and encoding a value to JSON:
func JSONHandler(f func(w http.ResponseWriter, r *http.Request) interface{}) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
v := f(w, r)
if v != nil {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(v); err != nil {
log.Println(err)
}
}
})
}
The argument to this function is a function that returns a value to encode to the response as JSON. For example, this function returns the client's user agent as JSON.
func UserAgentHandler(w http.ResponseWriter, r *http.Request) interface{} {
return struct { UserAgent string }{ req.Header.Get("User-Agent") }
}
Use the following code to register this handler with the Gorilla mux r:
r.Handle("/user-agent", JSONHandler(UserAgentHandler))
There are many ways to improve JSONHandler.

Resources