Add support for regex matching routes

This commit is contained in:
garrettmills 2020-07-30 09:03:29 -05:00
parent 7611c1b2bf
commit 194fa476ca
No known key found for this signature in database
GPG Key ID: 6ACD58D6ADACFC6E
3 changed files with 63 additions and 4 deletions

View File

@ -1,4 +1,3 @@
deepmatch route, regex match route
static assets static assets
middleware middleware
view engine view engine

View File

@ -0,0 +1,57 @@
import {Route, RouteParameters} from './Route.ts'
import {Logging} from '../../service/logging/Logging.ts'
import {make} from '../../../../di/src/global.ts'
export class RegExRoute extends Route {
protected key_regex: RegExp
constructor(
protected base: string,
protected key: string,
) {
super(base)
this.key_regex = this.build_regex(key)
}
public get route() {
return this.base + this.key
}
public match(incoming: string): boolean {
if ( !incoming.toLowerCase().startsWith(this.base) ) return false
incoming = incoming.substr(this.base.length)
const success = this.key_regex.test(incoming)
if ( !success ) {
make(Logging).debug(`RegExRoute match failed. (Testing: ${incoming}, Key: ${this.key}, Rex: ${this.key_regex})`)
}
return success
}
public build_parameters(incoming: string): RouteParameters {
if ( incoming.toLowerCase().startsWith(this.base) ) incoming = incoming.substr(this.base.length)
const results = this.key_regex.exec(incoming.toLowerCase())
if ( !results ) return {}
const [match, ...wildcards] = results
const params: RouteParameters = {}
let current_wildcard: number = 1
for ( const wild of wildcards ) {
params[`$${current_wildcard}`] = wild
current_wildcard += 1
}
return params
}
protected build_regex(key: string) {
if ( !key.startsWith('rex ') ) {
throw new TypeError(`Invalid regular expression route pattern: ${key}`)
}
return new RegExp(key.substr(4))
}
}

View File

@ -14,6 +14,7 @@ import {Logging} from '../service/logging/Logging.ts'
import {Canon} from './Canon.ts' import {Canon} from './Canon.ts'
import {isBindable} from '../lifecycle/AppClass.ts' import {isBindable} from '../lifecycle/AppClass.ts'
import {DeepmatchRoute} from "../http/routing/DeepmatchRoute.ts"; import {DeepmatchRoute} from "../http/routing/DeepmatchRoute.ts";
import {RegExRoute} from "../http/routing/RegExRoute.ts";
export type RouteHandler = (request: Request) => Request | Promise<Request> | ResponseFactory | Promise<ResponseFactory> | void | Promise<void> export type RouteHandler = (request: Request) => Request | Promise<Request> | ResponseFactory | Promise<ResponseFactory> | void | Promise<void>
export type RouteHandlers = RouteHandler[] export type RouteHandlers = RouteHandler[]
@ -74,7 +75,7 @@ export default class Routing extends LifecycleUnit {
// @ts-ignore // @ts-ignore
this.definitions[base][verb] = this.build_handler(handlers) this.definitions[base][verb] = this.build_handler(handlers)
this.instances.push(this.build_route(base)) this.instances.push(this.build_route(base, key))
} }
} }
} }
@ -136,8 +137,10 @@ export default class Routing extends LifecycleUnit {
return `/${joined}`.toLowerCase() return `/${joined}`.toLowerCase()
} }
public build_route(base: string): Route { public build_route(base: string, key: string): Route {
if ( !base.includes(':') && !base.includes('*') ) { if ( key.startsWith('rex ') ) {
return new RegExRoute(base.split(key)[0], key)
} else if ( !base.includes(':') && !base.includes('*') ) {
return new SimpleRoute(base) return new SimpleRoute(base)
} else if ( base.includes('**') ) { } else if ( base.includes('**') ) {
return new DeepmatchRoute(base) return new DeepmatchRoute(base)