Add support for deepmatch routes

This commit is contained in:
garrettmills 2020-07-30 08:17:49 -05:00
parent 42e8b36df4
commit 7611c1b2bf
No known key found for this signature in database
GPG Key ID: 6ACD58D6ADACFC6E
6 changed files with 77 additions and 8 deletions

25
TODO.txt Normal file
View File

@ -0,0 +1,25 @@
deepmatch route, regex match route
static assets
middleware
view engine
user-defined services
internationalization
uploads & universal path
CLI - view routes, template generation, start server, directives, output, args
request level error handler
develop/prod/debug modes
logger scope (e.g. logger.verbose())
favicon
utility - root, path, is_windows, is_linux, is_mac
authentication - user/session, oauth, jwt, &c.
orm relations, subqueries, enum/bit fields, json handlers, scopes
redis - redis client, redis rehydrated classes, redis sessions
less/scss
notifications - gotify/push/other mechanisms
forms
job queue - redis/db backed?
comment all the things
unit tests
integration tests
documentation & docs site
events and observables?

View File

@ -15,7 +15,7 @@ export default class ApiController extends BaseApiController {
} }
get_msg(request: Request) { get_msg(request: Request) {
return 'Hello, world!' return request.route.params
} }
get_redirect(request: Request) { get_redirect(request: Request) {

View File

@ -1,8 +1,8 @@
import Controller from "./Controller.ts"; import Controller from './Controller.ts'
import {Request} from "./Request.ts"; import {Request} from './Request.ts'
import ResponseFactory from "./response/ResponseFactory.ts"; import ResponseFactory from './response/ResponseFactory.ts'
import * as api from '../support/api.ts' import * as api from '../support/api.ts'
import JSONResponseFactory from "./response/JSONResponseFactory.ts"; import JSONResponseFactory from './response/JSONResponseFactory.ts'
export default class ApiController extends Controller { export default class ApiController extends Controller {
public get_bound_method(method_name: string): (...args: any[]) => any { public get_bound_method(method_name: string): (...args: any[]) => any {

View File

@ -22,7 +22,7 @@ export class ComplexRoute extends Route {
let current_wildcard: number = 1 let current_wildcard: number = 1
this.zip(incoming).forEach((segment: RouteSegment) => { this.zip(incoming).forEach((segment: RouteSegment) => {
if ( segment.base.indexOf('*') >= 0 ) { if ( segment.base === '*' ) {
params[`$${current_wildcard}`] = utility.infer(segment.match) params[`$${current_wildcard}`] = utility.infer(segment.match)
current_wildcard += 1 current_wildcard += 1
} else if ( segment.base.startsWith(':') && segment.base.length > 1 ) { } else if ( segment.base.startsWith(':') && segment.base.length > 1 ) {

View File

@ -0,0 +1,43 @@
import {Route, RouteParameters} from './Route.ts'
export class DeepmatchRoute extends Route {
protected base_regex: RegExp
constructor(
protected base: string
) {
super(base)
this.base_regex = this.build_regex(this.split(base))
}
public match(incoming: string): boolean {
return this.base_regex.test(incoming.toLowerCase())
}
public build_parameters(incoming: string): RouteParameters {
const results = this.base_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(base_parts: string[]) {
const deepmatch_group = '([a-zA-Z0-9\\-\\_\\.\\/]+)' // allows for alphanum, -, _, ., and /
const shallowmatch_group = '([a-zA-Z0-9\\-\\.\\_]+)' // allows for alphanum, -, ., and _
const regex = base_parts.map(part => {
return part.split('**').join(deepmatch_group).split('*').join(shallowmatch_group)
}).join('\\/')
return new RegExp(regex)
}
}

View File

@ -13,6 +13,7 @@ import {Canonical} from './Canonical.ts'
import {Logging} from '../service/logging/Logging.ts' 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";
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[]
@ -138,11 +139,11 @@ export default class Routing extends LifecycleUnit {
public build_route(base: string): Route { public build_route(base: string): Route {
if ( !base.includes(':') && !base.includes('*') ) { if ( !base.includes(':') && !base.includes('*') ) {
return new SimpleRoute(base) return new SimpleRoute(base)
} else if ( base.includes('**') ) {
return new DeepmatchRoute(base)
} else { } else {
return new ComplexRoute(base) return new ComplexRoute(base)
} }
// TODO deep-match route
} }
public match(incoming: string): Route | undefined { public match(incoming: string): Route | undefined {