jester
jester copied to clipboard
middleware support
Request for feature: middlewares, much like other frameworks do them. The basic principle is:
You have a chain of handler instances, each responding to a method that takes, at the very least, the request, a way to respond to the request, and the next handler as parameters.
They are called in sequence; each handler is responsible for calling into the next one. This results in a nested call chain, and allows each registered handler to:
- stop propagating the request and return data to the client - for example, to keep auth&auth in one place, or to add api/request throttling
- modify the request or environment (for example, handle content-type and transform the body data from/to json, and handle errors pertaining to that transparent to the framework user)
And many more usecases. A good search term for more information and examples would be "rack middleware".
Superset of #51? Most of the required functionality should be there if #51 was fixed, then it's just a matter of piecing it together as you want to.
After some discussion with @dom96 about the best methods of achieving packageable middleware, we are both at a loss for how it can be done currently and may need to consider adding additional functionality.
As can be seen in https://github.com/dom96/jester/blob/master/tests/alltest.nim#L165 there is the before
feature to get roughly the functionality we're looking for, however, it's not very extensible and wouldn't work well as far as packaging is concerned.
Per @dom96 https://github.com/dom96/jester/blob/master/jester.nim#L48 may be hookable to allow middleware to add it's own match procs, alongside register
to append (will need changes to prepend). How this could be optionally applied to only desired routes is yet to be seen.
Best thing to do in these kinds of situations is to see how other frameworks do it :)
I think you should stop thinking about how to mangle individual routes/matches. The middleware I thought would be useful would simply wrap the request at a lower level, like other implementations (cough rack cough) do it. Route matching is a different layer. IMHO, mingling the two adds confusion and needless complexity.
Apologies for pseudocode. You get the idea I hope.
proc myMiddleWare(r: Req, o: Resp, m: Next): .. =
if r.origin.wellLiked():
let before = time()
o.setCookie("hi", "there")
m.call(r, o)
let after = time()
o.setHeader("x-benchmark", after - before)
else:
info "Dropping ", r
jester.middlewareStack.insert myMiddleWare, 0
That said, I gave up on this for my previous use case so don't rush on my account.
I feel route matching/selective application of the middleware to desired routes is arguably the second most important feature of middleware short of its primary purpose of executing logic before the actual route's main logic.
What is the use of a login session manager/jwt middleware if even the login/register routes are protected?
I may be misunderstanding your previous comment, however, I think one potential solution would be to do it similarly to how Go's iris framework handles applying middleware to individual groups of api endpoints. Where in this example v1
has no middleware, but v2
has a jwt middleware:
func main() {
app := iris.Default()
// Simple group: v1.
v1 := app.Party("/v1")
{
v1.Post("/login", loginEndpoint)
v1.Post("/submit", submitEndpoint)
v1.Post("/read", readEndpoint)
}
// Simple group: v2.
v2 := app.Party("/v2", jwtHandler.Serve)
{
v2.Post("/login", loginEndpoint)
v2.Post("/submit", submitEndpoint)
v2.Post("/read", readEndpoint)
}
app.Run(iris.Addr(":8080"))
}
I'm not sure how we'd do it syntactically in jester but maybe something to the tune of this:
import jester
import authmiddleware
router api:
uses: authmiddleware.authenticate
get "/test":
resp "I'm authenticated!"
routes:
extend api, "/api"
Lack of middleware is a serious bane to the development experience when utilizing Jester.
If you look at other web micro-frameworks, you'll notice a great deal of them end up having packages developed that integrate at the middleware level. This helps promote the growth of tooling around those libraries.
I'm wondering how to add JWT into Jester, I can imagine the best way is through middleware layer, or does anybody know any of nim web app server supports the feature out of box?
You can already make use of libraries like nim-jwt fairly easily from Jester (there is at least one other library for this too). If you want middleware then you can check out @JohnAD's efforts: https://github.com/dom96/jester/pull/227
Thanks @dom96 !
@geohuz,
JWT is a fairly generic tool. Is there a general purpose for JWT you would like to see supported in a middleware package? Such as user authentication? (Such as seen for Python Django with https://jpadilla.github.io/django-rest-framework-jwt/ ?) Or for access to external service by your web site (such as Zapier?)
@JohnAD , If you look at python sanic framework, they have jwt as middleware supported very well.