Clean up middleware; solidify support for route handler classes

This commit is contained in:
Garrett Mills 2020-09-04 10:46:08 -05:00
parent ff34578d07
commit 27ee1a552b
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
5 changed files with 53 additions and 4 deletions

View File

@ -1,5 +1,12 @@
import Middleware from '../../../lib/src/http/Middleware.ts'
import {Request} from '../../../lib/src/http/Request.ts'
import {http} from '../../../lib/src/http/response/helpers.ts'
import {HTTPStatus} from '../../../lib/src/const/http.ts'
export default class TestMiddleware extends Middleware {
public async handleRequest(request: Request) {
if ( Math.random() >= 0.5 ) {
return http(HTTPStatus.FORBIDDEN, 'Well, you were unlucky.')
}
}
}

View File

@ -5,5 +5,6 @@ export default {
middleware: [],
get: {
'/': 'controller::Home.get_home',
'/maybe': ['middleware::Test', 'controller::Home.get_home'],
},
} as RouterDefinition

View File

@ -1,4 +1,6 @@
import AppClass from '../lifecycle/AppClass.ts'
import {Request} from './Request.ts'
import {RouteHandlerReturnValue} from '../unit/Routing.ts'
/**
* Base class for HTTP middleware.
@ -6,4 +8,13 @@ import AppClass from '../lifecycle/AppClass.ts'
*/
export default class Middleware extends AppClass {
/**
* Handle the incoming request and apply this middleware.
* @param {Request} request
* @return RouteHandlerReturnValue
*/
public handleRequest(request: Request): RouteHandlerReturnValue {
return
}
}

View File

@ -6,6 +6,7 @@ import {Request} from '../../Request.ts'
import ResponseFactory from '../../response/ResponseFactory.ts'
import {http, error} from '../../response/helpers.ts'
import {HTTPStatus} from '../../../const/http.ts'
import {isRouteHandlerClass} from "../../../unit/Routing.ts";
/**
* HTTP kernel module to apply route handlers to the incoming request.
@ -47,7 +48,13 @@ export default class ApplyRouteHandlers extends Module {
let current_request: Request = request
for ( const handler of request.route.handlers ) {
try {
const result = await handler(current_request)
let result
if ( isRouteHandlerClass(handler) ) {
result = await handler.handleRequest(current_request)
} else {
result = await handler(current_request)
}
if ( result instanceof Request ) {
// If we got a request instance back, use that for further handlers
current_request = result

View File

@ -16,10 +16,22 @@ import {isBindable} from '../lifecycle/AppClass.ts'
import {DeepmatchRoute} from "../http/routing/DeepmatchRoute.ts";
import {RegExRoute} from "../http/routing/RegExRoute.ts";
export type RouteHandlerReturnValue = SyncRouteHandlerReturnValue | AsyncRouteHandlerReturnValue
export type SyncRouteHandlerReturnValue = Request | ResponseFactory | void | undefined
export type AsyncRouteHandlerReturnValue = Promise<SyncRouteHandlerReturnValue>
export type RouteHandlerFunction = (request: Request) => RouteHandlerReturnValue
/**
* A class that can handle requests.
*/
export interface RouteHandlerClass {
handleRequest(request: Request): RouteHandlerReturnValue
}
/**
* Base type defining a single route handler.
*/
export type RouteHandler = (request: Request) => Request | Promise<Request> | ResponseFactory | Promise<ResponseFactory> | void | Promise<void>
export type RouteHandler = RouteHandlerFunction | RouteHandlerClass
/**
* Base type for a collection of route handlers.
@ -49,7 +61,18 @@ export interface RouteDefinition {
export function isRouteHandler(what: any): what is RouteHandler {
return (
typeof what === 'function'
|| typeof what.handleRequest === 'function'
|| isRouteHandlerClass(what)
)
}
/**
* Returns true if the gievn object is a route handling class.
* @param what
* @return boolean
*/
export function isRouteHandlerClass(what: any): what is RouteHandlerClass {
return (
what && typeof what.handleRequest === 'function' && what.handleRequest.length === 1
)
}