Usage with the path-to-regexp lib
iliyaZelenko opened this issue · comments
Илья commented
Vue router uses path-to-regexp.
Example proposal for this package:
{
from: '/library/:category/:book', to: '/new-library/:book'
}
It’s convenient when you can use this kind of parameters in URLs.
Илья commented
I created my middleware for redirects:
import { pathToRegexp, compile, parse } from 'path-to-regexp'
const redirectsBackwardCompatibility = [
{
from: '/article',
to: '/library'
},
{
from: '/article/post/:slug',
to: '/library/article/:slug'
},
{
from: '/community',
to: '/communities'
},
{
from: '/community/group/:group',
to: '/communities/group/:group'
},
{
from: '/community/group/:group/:section',
to: '/communities/group/:group#:section'
},
{
from: '/community/lenta/:community/:page',
to: '/community/:community/page/:page'
},
{
from: '/community/lenta_cat/:community/:category/:page',
to: '/community/:community/category/:category/page/:page'
},
{
from: '/user/lenta/:login/:page',
to: '/user/:login/page/:page'
},
{
from: '/user/lenta_cat/:login/:category/:page',
to: '/user/:login/category/:category/page/:page'
}
]
export default function (req, res, next) {
const url = decodeURI(req.url)
const matchedRule = redirectsBackwardCompatibility.find(i =>
pathToRegexp(i.from).exec(url)
)
if (!matchedRule) return next()
const re = pathToRegexp(matchedRule.from)
const toNewPath = compile(matchedRule.to)
const matchedRuleExecResult = re.exec(url)!
// первый элемент - не нужная строка
const paramsValues = matchedRuleExecResult.slice(1)
const paramsKeys = parse(matchedRule.to)
.filter(i => typeof i === 'object' && i.name)
// @ts-ignore
.map(i => i.name)
const paramsFinal = paramsKeys.reduce((prev, curr, index) => {
return {
...prev,
[curr]: paramsValues[index]
}
}, {})
const finalPath = toNewPath(paramsFinal)
try {
res.setHeader('Location', encodeURI(finalPath))
} catch (error) {
// Not passing the error as it's caused by URL that was user-provided so we
// can't do anything about the error.
return next()
}
res.statusCode = 301
res.end()
}