Middleware can't redirect without `router` in closure
nathanboktae opened this issue · comments
I am writing an authentication middleware, and I was hoping to simply do
var authToken
module.exports = function authMiddleware(transition) {
if (!authToken && transition.path !== '/login') {
return transition.redirect('/login?returnUrl=' + encodeURIComponent(transition.path))
}
}
but transition.redirect
or transition.transitionTo
doesn't exist on the transition. instead I have to have
var authToken
module.exports = {
initMiddleware: function(router) {
return function authMiddleware(transition) {
if (!authToken && transition.path !== '/login') {
router.transitionTo('/login?returnUrl=' + encodeURIComponent(transition.path))
return transition.followRedirects()
}
}
}
}
Much more awkward. It seems natural that middleware would want to do a redirect. Unless I'm missing something and there's a way to redirect without the router
?
Thanks for your continuous feedback, I appreciate it.
There used to be a transition.redirectTo
and I removed it to reduce the API surface. I wanted to try and keep as few functions as possible in cherrytree.
Having said that, you're right that it's useful for middleware to be able to redirect. We should bring that back. I wonder if
transition.redirectTo
(for symmetry with transitionTo) ortransition.redirect
- should we just expose the router instance on the transition itself..
transition.router
, since you might also want to userouter.replaceWith
,router.generate
and perhaps in same cases, inspect the router state..
The thing is, all that is possible simply by passing the router to the closure, so not sure how valuable it is to attach it to transitions. Makes transitions less like data and more like .. objecty thing.
E.g. in ES6, your middleware could look like:
module.exports.createAuthMiddleware = router => transition => {
if (!authToken && transition.path !== '/login') {
router.transitionTo('/login?returnUrl=' + encodeURIComponent(transition.path))
}
}
(no need to return the transition, redirecting immediately stops executing any further middleware and starts over with a new transition)
I wanted to try and keep as few functions as possible in cherrytree.
That's a good guiding principle and in cherrytree there seems to be only one way to do everything so that's good.
all that is possible simply by passing the router to the closure, so not sure how valuable it is to attach it to transitions
Imagine if server side middleware couldn't do a 301 or 302 without having the same object that configured all the routes. That'd feel really akward right? A transition
object that can be canceled and replaced but can't have a redirect is lacking IMO.
My vote is for transition.redirect
or transition.redirectTo
but I could see exposing the router, but to keep concerns separated I like the former.
Yeah, I'll add transition.redirectTo
which will wrap router.replaceWith
. Redirects should always be url "replacements", otherwise clicking browser's back button will most likely result in the same redirect rendering back button useless. Though need to test if this bit will work as I imagine.
Though need to test if this bit will work as I imagine.
Yeah I believe your right too here. Thanks!
Actually, it turns out that it doesn't matter which method is used for redirect since all transitions are already converted to replaceWiths when there's an ongoing active transition -
Lines 132 to 134 in 857b7ae
Anyways, this means that I just need to revert this change - 194a835