mirror of
https://github.com/honojs/hono.git
synced 2024-12-01 11:51:01 +01:00
fix(reg-exp-router): Register static paths first for duplicate checking. (#1146)
* fix(reg-exp-router): Register static paths first for duplicate checking. * chore: denoify
This commit is contained in:
parent
c09dbc060b
commit
2ff0605382
@ -29,20 +29,22 @@ function clearWildcardRegExpCache() {
|
||||
|
||||
function buildMatcherFromPreprocessedRoutes<T>(routes: [string, T[]][]): Matcher<T> {
|
||||
const trie = new Trie()
|
||||
const handlers: HandlerData<T>[] = []
|
||||
const handlerData: HandlerData<T>[] = []
|
||||
if (routes.length === 0) {
|
||||
return nullMatcher
|
||||
}
|
||||
|
||||
routes = routes.sort(([a], [b]) => a.length - b.length)
|
||||
const routesWithStaticPathFlag = routes
|
||||
.map((route) => [!/\*|\/:/.test(route[0]), ...route] as [boolean, string, T[]])
|
||||
.sort(([isStaticA, pathA], [isStaticB, pathB]) =>
|
||||
isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
|
||||
)
|
||||
|
||||
const staticMap: StaticMap<T> = {}
|
||||
for (let i = 0, j = -1, len = routes.length; i < len; i++) {
|
||||
const path = routes[i][0]
|
||||
let pathErrorCheckOnly = false
|
||||
if (!/\*|\/:/.test(path)) {
|
||||
pathErrorCheckOnly = true
|
||||
staticMap[routes[i][0]] = { handlers: routes[i][1], params: emptyParam }
|
||||
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
||||
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i]
|
||||
if (pathErrorCheckOnly) {
|
||||
staticMap[path] = { handlers, params: emptyParam }
|
||||
} else {
|
||||
j++
|
||||
}
|
||||
@ -58,15 +60,13 @@ function buildMatcherFromPreprocessedRoutes<T>(routes: [string, T[]][]): Matcher
|
||||
continue
|
||||
}
|
||||
|
||||
handlers[j] =
|
||||
paramMap.length === 0
|
||||
? [{ handlers: routes[i][1], params: emptyParam }, null]
|
||||
: [routes[i][1], paramMap]
|
||||
handlerData[j] =
|
||||
paramMap.length === 0 ? [{ handlers, params: emptyParam }, null] : [handlers, paramMap]
|
||||
}
|
||||
|
||||
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp()
|
||||
for (let i = 0, len = handlers.length; i < len; i++) {
|
||||
const paramMap = handlers[i][1]
|
||||
for (let i = 0, len = handlerData.length; i < len; i++) {
|
||||
const paramMap = handlerData[i][1]
|
||||
if (paramMap) {
|
||||
for (let j = 0, len = paramMap.length; j < len; j++) {
|
||||
paramMap[j][1] = paramReplacementMap[paramMap[j][1]]
|
||||
@ -77,7 +77,7 @@ function buildMatcherFromPreprocessedRoutes<T>(routes: [string, T[]][]): Matcher
|
||||
const handlerMap: HandlerData<T>[] = []
|
||||
// using `in` because indexReplacementMap is a sparse array
|
||||
for (const i in indexReplacementMap) {
|
||||
handlerMap[i] = handlers[indexReplacementMap[i]]
|
||||
handlerMap[i] = handlerData[indexReplacementMap[i]]
|
||||
}
|
||||
|
||||
return [regexp, handlerMap, staticMap] as Matcher<T>
|
||||
|
@ -222,24 +222,36 @@ describe('UnsupportedPathError', () => {
|
||||
}).toThrowError(UnsupportedPathError)
|
||||
})
|
||||
|
||||
it('static and dynamic', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
router.add('GET', '/reg-exp/router', 'foo')
|
||||
router.add('GET', '/reg-exp/:id', 'bar')
|
||||
describe('static and dynamic', () => {
|
||||
it('static first', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
router.add('GET', '/reg-exp/router', 'foo')
|
||||
router.add('GET', '/reg-exp/:id', 'bar')
|
||||
|
||||
expect(() => {
|
||||
router.match('GET', '/')
|
||||
}).toThrowError(UnsupportedPathError)
|
||||
})
|
||||
expect(() => {
|
||||
router.match('GET', '/')
|
||||
}).toThrowError(UnsupportedPathError)
|
||||
})
|
||||
|
||||
it('dynamic and static', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
router.add('GET', '/reg-exp/:id', 'bar')
|
||||
router.add('GET', '/reg-exp/router', 'foo')
|
||||
it('long label', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
router.add('GET', '/reg-exp/router', 'foo')
|
||||
router.add('GET', '/reg-exp/:service', 'bar')
|
||||
|
||||
expect(() => {
|
||||
router.match('GET', '/')
|
||||
}).toThrowError(UnsupportedPathError)
|
||||
expect(() => {
|
||||
router.match('GET', '/')
|
||||
}).toThrowError(UnsupportedPathError)
|
||||
})
|
||||
|
||||
it('dynamic first', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
router.add('GET', '/reg-exp/:id', 'bar')
|
||||
router.add('GET', '/reg-exp/router', 'foo')
|
||||
|
||||
expect(() => {
|
||||
router.match('GET', '/')
|
||||
}).toThrowError(UnsupportedPathError)
|
||||
})
|
||||
})
|
||||
|
||||
it('different regular expression', () => {
|
||||
|
@ -29,20 +29,22 @@ function clearWildcardRegExpCache() {
|
||||
|
||||
function buildMatcherFromPreprocessedRoutes<T>(routes: [string, T[]][]): Matcher<T> {
|
||||
const trie = new Trie()
|
||||
const handlers: HandlerData<T>[] = []
|
||||
const handlerData: HandlerData<T>[] = []
|
||||
if (routes.length === 0) {
|
||||
return nullMatcher
|
||||
}
|
||||
|
||||
routes = routes.sort(([a], [b]) => a.length - b.length)
|
||||
const routesWithStaticPathFlag = routes
|
||||
.map((route) => [!/\*|\/:/.test(route[0]), ...route] as [boolean, string, T[]])
|
||||
.sort(([isStaticA, pathA], [isStaticB, pathB]) =>
|
||||
isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
|
||||
)
|
||||
|
||||
const staticMap: StaticMap<T> = {}
|
||||
for (let i = 0, j = -1, len = routes.length; i < len; i++) {
|
||||
const path = routes[i][0]
|
||||
let pathErrorCheckOnly = false
|
||||
if (!/\*|\/:/.test(path)) {
|
||||
pathErrorCheckOnly = true
|
||||
staticMap[routes[i][0]] = { handlers: routes[i][1], params: emptyParam }
|
||||
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
||||
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i]
|
||||
if (pathErrorCheckOnly) {
|
||||
staticMap[path] = { handlers, params: emptyParam }
|
||||
} else {
|
||||
j++
|
||||
}
|
||||
@ -58,15 +60,13 @@ function buildMatcherFromPreprocessedRoutes<T>(routes: [string, T[]][]): Matcher
|
||||
continue
|
||||
}
|
||||
|
||||
handlers[j] =
|
||||
paramMap.length === 0
|
||||
? [{ handlers: routes[i][1], params: emptyParam }, null]
|
||||
: [routes[i][1], paramMap]
|
||||
handlerData[j] =
|
||||
paramMap.length === 0 ? [{ handlers, params: emptyParam }, null] : [handlers, paramMap]
|
||||
}
|
||||
|
||||
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp()
|
||||
for (let i = 0, len = handlers.length; i < len; i++) {
|
||||
const paramMap = handlers[i][1]
|
||||
for (let i = 0, len = handlerData.length; i < len; i++) {
|
||||
const paramMap = handlerData[i][1]
|
||||
if (paramMap) {
|
||||
for (let j = 0, len = paramMap.length; j < len; j++) {
|
||||
paramMap[j][1] = paramReplacementMap[paramMap[j][1]]
|
||||
@ -77,7 +77,7 @@ function buildMatcherFromPreprocessedRoutes<T>(routes: [string, T[]][]): Matcher
|
||||
const handlerMap: HandlerData<T>[] = []
|
||||
// using `in` because indexReplacementMap is a sparse array
|
||||
for (const i in indexReplacementMap) {
|
||||
handlerMap[i] = handlers[indexReplacementMap[i]]
|
||||
handlerMap[i] = handlerData[indexReplacementMap[i]]
|
||||
}
|
||||
|
||||
return [regexp, handlerMap, staticMap] as Matcher<T>
|
||||
|
Loading…
Reference in New Issue
Block a user