-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to set and reference redirectParams #2582
Comments
I'm not sure I'm getting it here. This is related to SSR, right? otherwise it wouldn't serve any purpose 🤔 |
Yes this is intended for SSR. |
Most of the time this can be handled before your vue application gets called server side, however it's nice to take advantage of vue-router's route matching capabilities and sometimes you need to make some API calls before knowing where to redirect the user. |
Here is a simplified example of what I'm trying to do. Routes [
{
path: '/foo':
redirect: '/foo-new',
redirectParams: {
responseCode: 301
}
},
{
path: '/bar':
redirect: '/bar-new',
redirectParams: {
responseCode: 302
}
},
{
path: '/foo-new',
component: FooNew,
},
{
path: '/bar-new',
component: BarNew
},
{
path: '*',
component: NotFound,
meta: {
notFound: true,
},
},
] Server side request handler module.exports = (req, res, next) => {
renderer.renderToString(context, (err, html) => {
if (err) {
if (err.redirectUrl) {
const responseCode = err.responseCode || HttpStatus.MOVED_TEMPORARILY
res.redirect(responseCode, err.redirectUrl)
} else if (err.notFound) {
res.status(HttpStatus.NOT_FOUND).send('404')
} else {
next(err)
}
return
}
res.send(html)
})
} Server entry point export default context => {
const router = createRouter()
const app = createApp(router)
return new Promise((resolve, reject) => {
router.onError(reject)
router.onReady(resolve, reject)
router.push(context.url)
})
.then(() => {
const to = router.currentRoute
if (to.meta.notFound) {
const error = new Error('Route not found')
error.notFound = true
return Promise.reject(error)
}
if (to.redirectedFrom) {
const error = new Error('Redirect')
error.redirectUrl = to.fullPath
error.responseCode = to.redirectParams.responseCode
return Promise.reject(error)
}
return app
})
} |
In cases where the route that you want to redirect to exists you could do [
{
path: '/foo':
redirect: {
name: 'fooNew',
params: {
responseCode: 301
}
}
},
{
path: '/bar':
redirect: {
name: 'barNew',
params: {
responseCode: 302
},
}
},
{
name: 'fooNew',
path: '/foo-new',
component: FooNew,
},
{
name: 'barNew',
path: '/bar-new',
component: BarNew
},
] But when the redirect is to a path outside of your application you don't get access to any sort of data like params because it ends up redirecting to the Not Found component. |
hey @atinux, do you think there is something we could work on together to make redirections? I think we should add some way of detecting what kind of navigation was triggered by the router. Keep some trace of a navigation being a redirect (#1822) and the kind of navigation (push/replace #1620) and the route the navigation came from #883 |
I understood better what you wanted after your reply on the RFC. This can be achieved with a |
@posva That definitely solves this issue, is a good idea, and closes the issue! However there are cases when calling Let's say we are migrating to a new url I've been able to achieve this by throwing errors with response codes on them and it all actually works fine in the RFC you've proposed. I think the only thing I'm looking for is the ability to optionally pass an http status code to I suppose you could do next({ name: 'newRoute', params: { httpStatusCode: 301 } }) |
For that scenario, you should still be able to use
Then, in the code checking for Passing |
You're solution to this implies that you decide up front in the route meta configuration the redirect repsonse code that it always issues. What if you wanted in some cases to issue a 301 redirect from a route and in other cases a 302 redirect from that same route. For example, a 302 if the user isn't authenticated and a 301 redirect to the new url if they are. You could say I'll let the new url handle the auth code and always 301 from the old url but I'm sure there are examples where a developer might want to have the fine grained control to say for this route in this case do a 301 and in another case do a 302. That decison feels like it should come from within the application logic and not the route configuration. |
For those cases, the value should be saved in some global state like the store so the status code is retrievable before responding to the request |
@posva that is an interesting idea. I think another similar solution would be to update the serverContext object. Thank you! |
I'm not sure what you are referring by |
Correct! Sorry for the confusion I was referring to the context object that you pass into an server entry point. https://ssr.vuejs.org/guide/structure.html#entry-server-js. A new one gets created per request and it can be mutated over the course of a request with response headers and other server specific info needed for responding. Seems like the perfect thing to set a responseCode on. |
Yes, that's perfect. I'm closing this but we will have to document this specific part about using the server context to setup redirections |
What problem does this feature solve?
In order to issue a 301 redirect vs a 302 redirect in vue router there is no easy way to do that in userland. Currently you have to write a custom redirect function and throw an error with the information that you need.
What does the proposed API look like?
In your redirects you can define
And in a
beforeEach
handler you could reference the meta infoThe text was updated successfully, but these errors were encountered: