From 0764085ef928987489d6ec54a4e4fb230f696bc8 Mon Sep 17 00:00:00 2001 From: garrettmills Date: Wed, 29 Jul 2020 22:55:17 -0500 Subject: [PATCH] Improve response factories and add helper functions --- app/http/controllers/Test.controller.ts | 15 ++++++---- .../DehydratedStateResponseFactory.ts | 1 + lib/src/http/response/ErrorResponseFactory.ts | 19 +++++++++---- lib/src/http/response/HTMLResponseFactory.ts | 17 +++++++++++ lib/src/http/response/JSONResponseFactory.ts | 1 + lib/src/http/response/ResponseFactory.ts | 12 +++++++- .../http/response/StringResponseFactory.ts | 1 + .../TemporaryRedirectResponseFactory.ts | 18 ++++++++++++ lib/src/http/response/helpers.ts | 28 +++++++++++++++++++ 9 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 lib/src/http/response/HTMLResponseFactory.ts create mode 100644 lib/src/http/response/TemporaryRedirectResponseFactory.ts create mode 100644 lib/src/http/response/helpers.ts diff --git a/app/http/controllers/Test.controller.ts b/app/http/controllers/Test.controller.ts index d5fbb78..1120435 100644 --- a/app/http/controllers/Test.controller.ts +++ b/app/http/controllers/Test.controller.ts @@ -1,13 +1,18 @@ import Controller from '../../../lib/src/http/Controller.ts' +import {Request} from '../../../lib/src/http/Request.ts' +import {error, html, redirect} from '../../../lib/src/http/response/helpers.ts' export default class TestController extends Controller { - get_home(req: any) { - req.response.body = 'Hello!' + get_home(request: Request) { + return html('

Hi!

') } - get_user_home(req: any) { - throw new Error('Hello, world!') + + get_user_home(request: Request) { + return redirect('/home') } - create_user_home(req: any) {} + create_user_home(request: Request) { + return error('Not implemented!') + } } diff --git a/lib/src/http/response/DehydratedStateResponseFactory.ts b/lib/src/http/response/DehydratedStateResponseFactory.ts index 2815d79..d1519d2 100644 --- a/lib/src/http/response/DehydratedStateResponseFactory.ts +++ b/lib/src/http/response/DehydratedStateResponseFactory.ts @@ -10,6 +10,7 @@ export default class DehydratedStateResponseFactory extends ResponseFactory { } public async write(request: Request): Promise { + request = await super.write(request) request.response.body = JSON.stringify(this.rehydratable.dehydrate()) return request } diff --git a/lib/src/http/response/ErrorResponseFactory.ts b/lib/src/http/response/ErrorResponseFactory.ts index ab52563..ec47eb3 100644 --- a/lib/src/http/response/ErrorResponseFactory.ts +++ b/lib/src/http/response/ErrorResponseFactory.ts @@ -1,17 +1,26 @@ -import ResponseFactory from "./ResponseFactory.ts"; -import {Request} from "../Request.ts"; +import ResponseFactory from './ResponseFactory.ts' +import {Request} from '../Request.ts' export default class ErrorResponseFactory extends ResponseFactory { + protected target_mode: 'json' | 'html' = 'html' + constructor( public readonly error: Error, - public readonly output: 'json' | 'html' = 'html', - public readonly status: number = 500, + status: number = 500, + output: 'json' | 'html' = 'html', ) { super() + this.status(status) + this.mode(output) + } + + public mode(output: 'json' | 'html'): ErrorResponseFactory { + this.target_mode = output + return this } public async write(request: Request): Promise { - request.response.status = this.status + request = await super.write(request) if ( this.output === 'json' ) { request.response.headers.set('Content-Type', 'application/json') diff --git a/lib/src/http/response/HTMLResponseFactory.ts b/lib/src/http/response/HTMLResponseFactory.ts new file mode 100644 index 0000000..78205a1 --- /dev/null +++ b/lib/src/http/response/HTMLResponseFactory.ts @@ -0,0 +1,17 @@ +import ResponseFactory from './ResponseFactory.ts' +import {Request} from '../Request.ts' + +export default class HTMLResponseFactory extends ResponseFactory { + constructor( + public readonly value: string, + ) { + super() + } + + public async write(request: Request): Promise { + request = await super.write(request) + request.response.headers.set('Content-Type', 'text/html') + request.response.body = this.value + return request + } +} diff --git a/lib/src/http/response/JSONResponseFactory.ts b/lib/src/http/response/JSONResponseFactory.ts index 6a4b680..2ff97ad 100644 --- a/lib/src/http/response/JSONResponseFactory.ts +++ b/lib/src/http/response/JSONResponseFactory.ts @@ -9,6 +9,7 @@ export default class JSONResponseFactory extends ResponseFactory { } public async write(request: Request): Promise { + request = await super.write(request) request.response.headers.set('Content-Type', 'application/json') request.response.body = JSON.stringify(this.value) return request diff --git a/lib/src/http/response/ResponseFactory.ts b/lib/src/http/response/ResponseFactory.ts index d620b6c..1eb24f4 100644 --- a/lib/src/http/response/ResponseFactory.ts +++ b/lib/src/http/response/ResponseFactory.ts @@ -2,5 +2,15 @@ import AppClass from '../../lifecycle/AppClass.ts' import {Request} from '../Request.ts' export default abstract class ResponseFactory extends AppClass { - public abstract async write(request: Request): Promise + protected target_status: number = 200 + + public async write(request: Request): Promise { + request.response.status = this.target_status + return request + } + + public status(status: number): ResponseFactory { + this.target_status = status + return this + } } diff --git a/lib/src/http/response/StringResponseFactory.ts b/lib/src/http/response/StringResponseFactory.ts index 7d80de0..541d752 100644 --- a/lib/src/http/response/StringResponseFactory.ts +++ b/lib/src/http/response/StringResponseFactory.ts @@ -9,6 +9,7 @@ export default class StringResponseFactory extends ResponseFactory { } public async write(request: Request): Promise { + request = await super.write(request) request.response.body = this.value return request } diff --git a/lib/src/http/response/TemporaryRedirectResponseFactory.ts b/lib/src/http/response/TemporaryRedirectResponseFactory.ts new file mode 100644 index 0000000..03f8a66 --- /dev/null +++ b/lib/src/http/response/TemporaryRedirectResponseFactory.ts @@ -0,0 +1,18 @@ +import ResponseFactory from './ResponseFactory.ts' +import {Request} from '../Request.ts' + +export default class TemporaryRedirectResponseFactory extends ResponseFactory { + protected target_status: number = 301 + + constructor( + public readonly destination: string, + ) { + super() + } + + public async write(request: Request): Promise { + request = await super.write(request) + request.response.headers.set('Location', this.destination) + return request + } +} diff --git a/lib/src/http/response/helpers.ts b/lib/src/http/response/helpers.ts new file mode 100644 index 0000000..ec0a8c1 --- /dev/null +++ b/lib/src/http/response/helpers.ts @@ -0,0 +1,28 @@ +import JSONResponseFactory from './JSONResponseFactory.ts' +import {make} from '../../../../di/src/global.ts' +import HTMLResponseFactory from './HTMLResponseFactory.ts' +import ErrorResponseFactory from './ErrorResponseFactory.ts' +import {Rehydratable} from '../../support/Rehydratable.ts' +import DehydratedStateResponseFactory from './DehydratedStateResponseFactory.ts' +import TemporaryRedirectResponseFactory from './TemporaryRedirectResponseFactory.ts' + +export function json(value: any): JSONResponseFactory { + return make(JSONResponseFactory, value) +} + +export function html(value: string): HTMLResponseFactory { + return make(HTMLResponseFactory, value) +} + +export function error(error: Error | string, status: number = 500): ErrorResponseFactory { + if ( typeof error === 'string' ) error = new Error(error) + return make(ErrorResponseFactory, error, status) +} + +export function dehydrate(value: Rehydratable): DehydratedStateResponseFactory { + return make(DehydratedStateResponseFactory, value) +} + +export function redirect(destination: string): TemporaryRedirectResponseFactory { + return make(TemporaryRedirectResponseFactory, destination) +}