Invoke decode manually
dnguyenzd opened this issue · 2 comments
Thanks for this useful library
It's just a personal opinion but I find using a middleware to parse request parameters and pass the parsed values to handlers through context a bit odd. I prefer calling decode manually in a handler and handle error in the handler itself. To do that, I need to do something like this at the moment:
engine, err := httpin.New(MyParams{})
if err != nil {
return nil, err
}
input, err := engine.Decode(req)
if err != nil {
return nil, err
}
return input.(*MyParams), nil
it's much more friendly if it exposes a single function to invoke like err := httpin.Decode(req, &myParams)
. This requires a default engine that is not dependent on any specific input and might be a big change though
Hi @dnguyenzd, thanks for the suggestion. This should be considered as an API enhancement. Technically it is feasible.
It's just a personal opinion but I find using a middleware to parse request parameters and pass the parsed values to handlers through context a bit odd.
Middlewares and contexts are used frequently, so I don't think it will be an issue. And compared to decoding manually, using the httpin middleware can handle parsing problems of request parameters centralizedly. It will bring benefit of a better maintainability, as it conforms to the "fail fast" coding strategy. It can avoid stepping into the main handler when confronted with errors.
BTW, different people have different tastes. I can understand that some people including you prefer calling the decode function manually. I'm also glad to add this API if I can hear more requests from the community. So I will keep this ticket open.
Firstly, I have to point out that, when using httpin.NewInput
to create a middleware, the inner Engine
object will be reused in each request. It has a better performance than creating an engine during each request as creating an engine is not a "fast" operation.
Secondly, I'd like to listen more from the community. I believe we prefer a tiny library. Which means eliminating an API should be much more welcome than adding an API.
Thirdly, at this moment, I suggest you implementing the httpin.Decode
as a helper in your own package. You can use httpin.New
to create engines, but don't forget to reuse them, and take the variadic parameters opts
into account.
This requires a default engine that is not dependent on any specific input and might be a big change though
Maybe the name Engine
is a little confusing here. Actually, an engine in httpin is bound to a specific struct type. So here the wanted API httpin.Decode
should be a place to pick a correct engine and then parse the request.
Actually, after some investigation. I found that the reuse of the built engine had already been implemented. I just fogot that. So I'm going to ship this feature.