mirror of
https://github.com/honojs/hono.git
synced 2024-12-01 11:51:01 +01:00
feat(reg-exp-router): regexp support path including slashes. (#789)
* feat(reg-exp-router): `regexp` support path including slashes. * chore: denoify
This commit is contained in:
parent
b723faa81f
commit
9bc52a5ddd
@ -11,14 +11,37 @@ export class Trie {
|
||||
insert(path: string, index: number): ParamMap {
|
||||
const paramMap: ParamMap = []
|
||||
|
||||
const groups: [string, string][] = [] // [mark, original string]
|
||||
for (let i = 0;;) {
|
||||
let replaced = false
|
||||
path = path.replace(/\{[^}]+\}/g, (m) => {
|
||||
const mark = `@\\${i}`
|
||||
groups[i] = [mark, m]
|
||||
i++
|
||||
replaced = true
|
||||
return mark
|
||||
})
|
||||
if (!replaced) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* - pattern (:label, :label{0-9]+}, ...)
|
||||
* - /* wildcard
|
||||
* - character
|
||||
*/
|
||||
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g)
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || []
|
||||
for (let i = groups.length - 1; i >= 0; i--) {
|
||||
const [mark] = groups[i]
|
||||
for (let j = tokens.length - 1; j >= 0; j--) {
|
||||
if (tokens[j].indexOf(mark) !== -1) {
|
||||
tokens[j] = tokens[j].replace(mark, groups[i][1])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.root.insert(tokens, index, paramMap, this.context)
|
||||
|
||||
return paramMap
|
||||
|
@ -330,6 +330,54 @@ describe('long prefix, then star', () => {
|
||||
expect(res?.handlers).toEqual(['long-prefix', 'long', 'star1', 'star2'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('Including slashes', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
|
||||
router.add('GET', '/js/:filename{[a-z0-9/]+.js}', 'any file')
|
||||
|
||||
// XXX This route can not be added with `:label` to RegExpRouter. This is ambiguous.
|
||||
// router.add('GET', '/js/main.js', 'main.js')
|
||||
// it('get /js/main.js', () => {
|
||||
// const res = router.match('GET', '/js/main.js')
|
||||
// expect(res).not.toBeNull()
|
||||
// expect(res?.handlers).toEqual(['any file', 'main.js'])
|
||||
// expect(res?.params).toEqual({ filename: 'main.js' })
|
||||
// })
|
||||
|
||||
it('get /js/chunk/123.js', () => {
|
||||
const res = router.match('GET', '/js/chunk/123.js')
|
||||
expect(res).not.toBeNull()
|
||||
expect(res?.handlers).toEqual(['any file'])
|
||||
expect(res?.params).toEqual({ filename: 'chunk/123.js' })
|
||||
})
|
||||
|
||||
it('get /js/chunk/nest/123.js', () => {
|
||||
const res = router.match('GET', '/js/chunk/nest/123.js')
|
||||
expect(res).not.toBeNull()
|
||||
expect(res?.handlers).toEqual(['any file'])
|
||||
expect(res?.params).toEqual({ filename: 'chunk/nest/123.js' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('REST API', () => {
|
||||
const router = new RegExpRouter<string>()
|
||||
|
||||
router.add('GET', '/users/:username{[a-z]+}', 'profile')
|
||||
router.add('GET', '/users/:username{[a-z]+}/posts', 'posts')
|
||||
|
||||
it('get /users/hono', () => {
|
||||
const res = router.match('GET', '/users/hono')
|
||||
expect(res).not.toBeNull()
|
||||
expect(res?.handlers).toEqual(['profile'])
|
||||
})
|
||||
|
||||
it('get /users/hono/posts', () => {
|
||||
const res = router.match('GET', '/users/hono/posts')
|
||||
expect(res).not.toBeNull()
|
||||
expect(res?.handlers).toEqual(['posts'])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('static routes of ALL and GET', () => {
|
||||
|
@ -11,14 +11,37 @@ export class Trie {
|
||||
insert(path: string, index: number): ParamMap {
|
||||
const paramMap: ParamMap = []
|
||||
|
||||
const groups: [string, string][] = [] // [mark, original string]
|
||||
for (let i = 0;;) {
|
||||
let replaced = false
|
||||
path = path.replace(/\{[^}]+\}/g, (m) => {
|
||||
const mark = `@\\${i}`
|
||||
groups[i] = [mark, m]
|
||||
i++
|
||||
replaced = true
|
||||
return mark
|
||||
})
|
||||
if (!replaced) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* - pattern (:label, :label{0-9]+}, ...)
|
||||
* - /* wildcard
|
||||
* - character
|
||||
*/
|
||||
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g)
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || []
|
||||
for (let i = groups.length - 1; i >= 0; i--) {
|
||||
const [mark] = groups[i]
|
||||
for (let j = tokens.length - 1; j >= 0; j--) {
|
||||
if (tokens[j].indexOf(mark) !== -1) {
|
||||
tokens[j] = tokens[j].replace(mark, groups[i][1])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.root.insert(tokens, index, paramMap, this.context)
|
||||
|
||||
return paramMap
|
||||
|
Loading…
Reference in New Issue
Block a user