import Module from '../Module.ts' import {Injectable} from '../../../../../di/src/decorator/Injection.ts' import Kernel from '../Kernel.ts' import {Logging} from '../../../service/logging/Logging.ts' import {Request} from '../../Request.ts' import ResponseFactory from '../../response/ResponseFactory.ts' import {http, error} from '../../response/helpers.ts' import {HTTPStatus} from '../../../const/http.ts' /** * HTTP kernel module to apply route handlers to the incoming request. * @extends Module */ @Injectable() export default class ApplyRouteHandlers extends Module { public static register(kernel: Kernel) { kernel.register(this).core() } constructor( protected readonly logger: Logging, ) { super() } /** * Apply the route handler to the request. * @param {Request} request * @return Promise */ public async apply(request: Request): Promise { if ( !request.route ) { // Route not found const factory = http(HTTPStatus.NOT_FOUND) return await factory.write(request) } if ( !Array.isArray(request.route.handlers) ) { // Route found but invalid HTTP method const factory = http(HTTPStatus.METHOD_NOT_ALLOWED) return await factory.write(request) } if ( request.route.handlers.length < 1 ) { // Route and method found, but no handlers const factory = http(HTTPStatus.NOT_IMPLEMENTED) return await factory.write(request) } let current_request: Request = request for ( const handler of request.route.handlers ) { try { const result = await handler(current_request) if ( result instanceof Request ) { // If we got a request instance back, use that for further handlers current_request = result } else if ( result instanceof ResponseFactory ) { // If we got a response factory back, write the response and move along return await result.write(current_request) } } catch (e) { this.logger.error('Error encountered while applying request handlers!') this.logger.error(e) // TODO determine response type (html | json, &c.) const factory = error(e) return await factory.write(request) } } return current_request } }