UNPKG

http-micro

Version:

Micro-framework on top of node's http module

221 lines (183 loc) 6.87 kB
import { Middleware, IApplication, Application } from "./core"; import * as http from "http"; import * as url from "url"; import { stringify } from "./utils"; import { isString } from "./lang"; import { RouteContext } from "./route-context"; import * as bodyParser from "./body-parser"; import * as contentType from "content-type"; import { intoHttpError } from "./error-utils"; import { RequestUtils, ResponseUtils } from "./context-utils"; import * as httpError from "http-errors"; export class Context { items: Map<string, any>; requestParser: bodyParser.Parser; private _contentType: contentType.MediaType; private _url: url.Url = null; private _ipAddresses: string[] = null; private _routeContext: RouteContext = null; private _bodyParseTask: any = null; constructor( public app: IApplication, public req: http.IncomingMessage, public res: http.ServerResponse, requestParser?: bodyParser.Parser) { if (requestParser !== undefined) this.requestParser = requestParser; if (this.requestParser === undefined) this.requestParser = bodyParser.anyBodyParserFactory(); } getItem<T = any>(key: string): T { if (this.items) { let res = this.items.get(key); if (res !== undefined) return res; } let appItems = this.app.items; if (appItems) { let res = appItems.get(key); if (res !== undefined) return res; } return null; } setItem<T = any>(key: string, value: T): void { if (!this.items) { this.items = new Map<string, any>(); } this.items.set(key, value); } hasItem(key: string): boolean { if (this.items) { let res = this.items.has(key); if (res) return res; } let appItems = this.app.items; if (appItems) { let res = appItems.get(key); if (res) return res; } return false; } getUrl() { if (this._url === null) { this._url = url.parse(this.req.url); } return this._url; } getRouteContext() { return this._routeContext || (this._routeContext = new RouteContext(this.getUrl().pathname)); } getRouteParams() { return this.getRouteContext().params; } getHttpMethod() { return this.req.method; } getRequestStream() { // TODO: Do request stream pre-processing, like // Content-Encoding, Transfer-Encoding of gzip, etc. return this.req; } getResponseStream() { // TODO: Do post processing of stream, like // Content-Encoding, Transfer-Encoding of gzip, etc. return this.res; } getRequestBody<T>(parser?: bodyParser.Parser): Promise<T> { if (this._bodyParseTask === null) { let task = bodyParser.parseBody<T>(this.getRequestStream(), null, parser || this.requestParser); this._bodyParseTask = task; return task; } return this._bodyParseTask; } getContentType() { if (this._contentType !== undefined) return this._contentType; return (this._contentType = RequestUtils.getContentType(this.req)); } getClientIpAddress() { return this.getUpstreamIpAddresses()[0]; } getUpstreamIpAddresses() { let existing = this._ipAddresses; if (existing) return existing; return this._ipAddresses = RequestUtils.getUpstreamIpAddresses(this.req); } getHost(): string { return RequestUtils.getHost(this.req); } getProtocol(): string { return RequestUtils.getProtocol(this.req); } isEncrypted() { return RequestUtils.isEncrypted(this.req); } setHeader(key: string, value: string, replace = true) { return ResponseUtils.setHeader(this.res, key, value, replace); } setHeaders(headers: any) { ResponseUtils.setHeaders(this.res, headers); } appendHeaderValue(key: string, value: string, forceAppend = false) { ResponseUtils.appendHeaderValue(this.res, key, value, forceAppend); } removeHeaderValue(key: string, value: string, removeHeaderIfEmpty = true) { ResponseUtils.removeHeaderValue(this.res, key, value, removeHeaderIfEmpty); } setContentType(value: string, force = false) { ResponseUtils.setContentType(this.res, value, force); } setStatus(code: number, message?: string) { ResponseUtils.setStatus(this.res, code, message); } sendStatus(code: number, message?: string, headers?: any) { ResponseUtils.sendStatus(this.res, code, message, headers); } send(body: any, headers?: any, code = 200) { ResponseUtils.send(this.res, body, headers, code); } sendText(text: string) { ResponseUtils.sendText(this.res, text); } sendAsJson(data: any, replacer?: (key: string, value: any) => any, spaces?: string | number) { ResponseUtils.sendAsJson(this.res, data, replacer, spaces); } sendNoContent(headers?: any) { ResponseUtils.sendNoContent(this.res, headers); } sendResetContent(headers?: any) { ResponseUtils.sendResetContent(this.res, headers); } sendBadRequest(body: any, headers?: any) { ResponseUtils.sendBadRequest(this.res, body, headers); } sendNotFound(reason: string = null, headers?: any) { ResponseUtils.sendNotFound(this.res, reason, headers); } sendForbidden(reason: any, headers?: any) { ResponseUtils.sendForbidden(this.res, reason, headers); } sendMethodNotAllowed(allowedMethods: string[] | string, reason: string = null, headers?: any) { ResponseUtils.sendMethodNotAllowed(this.res, allowedMethods, reason, headers); } throw(error: Error): never; throw(status: number, error: Error): never; throw(status: number, msg?: string): never; throw(arg1: number | Error, arg2?: string | Error): never { if (typeof arg1 !== "number") { let status = arg1; throw intoHttpError(status); } let status = arg1; if (!arg2 || typeof arg2 === "string") { let msg = arg2; throw httpError(status, msg); } let error = arg2; throw intoHttpError(error, status, true); } } export function contextFactory(app: IApplication, req: http.IncomingMessage, res: http.ServerResponse, parser?: bodyParser.Parser) { return new Context(app, req, res, parser); }