UNPKG

@dooboostore/simple-boot-http-server

Version:

back end http server frameworks

313 lines 22.3 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { SimpleApplication } from '@dooboostore/simple-boot/SimpleApplication'; import { HttpServerOption } from './option/HttpServerOption'; import { IncomingMessage, Server as HttpServer, ServerResponse } from 'http'; import { Server as HttpsServer } from 'https'; import { RequestResponse } from './models/RequestResponse'; import { getUrlMapping, getUrlMappings, UrlMappingSituationType } from './decorators/MethodMapping'; import { HttpStatus } from './codes/HttpStatus'; import { HttpHeaders } from './codes/HttpHeaders'; import { Mimes } from './codes/Mimes'; import { ExceptionHandlerSituationType, targetExceptionHandler } from '@dooboostore/simple-boot/decorators/exception/ExceptionDecorator'; import { getInject, SituationTypeContainer, SituationTypeContainers } from '@dooboostore/simple-boot/decorators/inject/Inject'; import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils'; import { ReqFormUrlBody } from './models/datas/body/ReqFormUrlBody'; import { ReqJsonBody } from './models/datas/body/ReqJsonBody'; import { ReqHeader } from './models/datas/ReqHeader'; import { RouterModule } from '@dooboostore/simple-boot/route/RouterModule'; import { ReqMultipartFormBody } from './models/datas/body/ReqMultipartFormBody'; import { execValidationInValid, getValidIndex } from '@dooboostore/simple-boot/decorators/validate/Validation'; import { ValidException } from '@dooboostore/simple-boot/errors/ValidException'; import { HttpError } from './errors/HttpError'; import { getRoute } from '@dooboostore/simple-boot/decorators/route/Router'; import { URLSearchParams } from 'url'; import { HttpMethod } from './codes/HttpMethod'; import { SessionManager } from './session/SessionManager'; import { InjectSituationType } from './inject/InjectSituationType'; export class SimpleBootHttpServer extends SimpleApplication { constructor(option = new HttpServerOption()) { super(option); this.option = option; this.sessionManager = new SessionManager(this.option); } run(otherInstanceSim) { var _a, _b, _c, _d; const simstanceManager = super.run(otherInstanceSim); const targets = [...(_a = this.option.closeEndPoints) !== null && _a !== void 0 ? _a : [], ...(_b = this.option.errorEndPoints) !== null && _b !== void 0 ? _b : [], ...(_c = this.option.requestEndPoints) !== null && _c !== void 0 ? _c : [], ...(_d = this.option.filters) !== null && _d !== void 0 ? _d : []]; Promise.all(targets.map(it => (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it)).map(it => it.onInit(this))).then(it => { this.startServer(); }); return simstanceManager; } startServer() { const _super = Object.create(null, { routing: { get: () => super.routing } }); if (this.option.serverOption && 'key' in this.option.serverOption && 'cert' in this.option.serverOption) { this.server = new HttpsServer(this.option.serverOption); const httpServer = new HttpServer(); httpServer.on('request', (req, res) => { res.writeHead(301, { Location: `https://${req.headers.host}${req.url}` }); res.end(); }); httpServer.listen(80, this.option.listen.hostname, () => { console.log('HTTP redirect server running on port 80'); }); } else if (this.option.serverOption) { this.server = new HttpServer(this.option.serverOption); } else { this.server = new HttpServer(); } this.server.on('request', (req, res) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z; const transactionManager = this.option.transactionManagerFactory ? yield this.option.transactionManagerFactory() : undefined; res.on('close', () => __awaiter(this, void 0, void 0, function* () { if (this.option.closeEndPoints) { for (const it of this.option.closeEndPoints) { try { const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it); const endPoint = execute === null || execute === void 0 ? void 0 : execute.endPoint(rr, this); if (endPoint instanceof Promise) { yield endPoint; } } catch (e) { } } } if (!rr.resIsDone()) { rr.resEnd(); } })); res.on('error', () => __awaiter(this, void 0, void 0, function* () { if (this.option.errorEndPoints) { for (const it of this.option.errorEndPoints) { try { const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it); const endPoint = execute === null || execute === void 0 ? void 0 : execute.endPoint(rr, this); if (endPoint instanceof Promise) { yield endPoint; } } catch (e) { } } } if (!rr.resIsDone()) { rr.resEnd(); } })); const rr = new RequestResponse(req, res, { sessionManager: this.sessionManager, option: this.option }); rr.resSetHeader(HttpHeaders.Server, 'simple-boot-http-server'); const cookie = rr.reqCookieGet(this.option.sessionOption.key); if (!cookie) { const session = yield this.sessionManager.session(); rr.resSetHeader(HttpHeaders.SetCookie, `${this.option.sessionOption.key}=${session.uuid}; Path=/; HttpOnly`); } const otherStorage = new Map(); otherStorage.set(RequestResponse, rr); otherStorage.set(IncomingMessage, req); otherStorage.set(ServerResponse, res); try { transactionManager === null || transactionManager === void 0 ? void 0 : transactionManager.try(); if (this.option.requestEndPoints) { for (const it of this.option.requestEndPoints) { try { const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it); execute === null || execute === void 0 ? void 0 : execute.endPoint(rr, this); } catch (e) { } } } const filter = { carrier: new Map(), filters: [] }; for (let i = 0; this.option.filters && i < this.option.filters.length; i++) { const it = this.option.filters[i]; const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it); let sw = true; if (execute === null || execute === void 0 ? void 0 : execute.proceedBefore) { sw = yield execute.proceedBefore({ rr, app: this, carrier: filter.carrier }); filter.filters.push({ filter: execute, sw }); } if (!sw) { break; } } if (!rr.resIsDone()) { const routerModule = yield _super.routing.call(this, rr.reqIntent); otherStorage.set(RouterModule, routerModule); const moduleInstance = (_a = routerModule === null || routerModule === void 0 ? void 0 : routerModule.getModuleInstance) === null || _a === void 0 ? void 0 : _a.call(routerModule); let methods = []; if (routerModule && moduleInstance) { if (routerModule.propertyKeys) { const map = (_b = routerModule.propertyKeys) === null || _b === void 0 ? void 0 : _b.map((it) => { return { propertyKey: it, config: getUrlMapping(moduleInstance, it) }; }); methods.push(...(map !== null && map !== void 0 ? map : [])); } else { methods.push(...((_c = getUrlMappings(moduleInstance).filter(it => !getRoute(moduleInstance, it.propertyKey))) !== null && _c !== void 0 ? _c : [])); } if (((_d = rr.reqMethod()) === null || _d === void 0 ? void 0 : _d.toUpperCase()) === HttpMethod.OPTIONS.toUpperCase()) { rr.resSetHeader(HttpHeaders.Allow, methods.map(it => it.config.method).join(', ')); rr.resStatusCode(HttpStatus.Ok); } methods = methods.filter(it => { var _a; return it && it.propertyKey && it.config && ((_a = rr.reqMethod()) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === it.config.method.toUpperCase(); }); methods.sort((a, b) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; return (((_d = (_c = (_b = (_a = b.config) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.contentType) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) + ((_h = (_g = (_f = (_e = b.config) === null || _e === void 0 ? void 0 : _e.req) === null || _f === void 0 ? void 0 : _f.accept) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0)) - (((_m = (_l = (_k = (_j = a.config) === null || _j === void 0 ? void 0 : _j.req) === null || _k === void 0 ? void 0 : _k.contentType) === null || _l === void 0 ? void 0 : _l.length) !== null && _m !== void 0 ? _m : 0) + ((_r = (_q = (_p = (_o = a.config) === null || _o === void 0 ? void 0 : _o.req) === null || _p === void 0 ? void 0 : _p.accept) === null || _q === void 0 ? void 0 : _q.length) !== null && _r !== void 0 ? _r : 0)); }); methods = methods .filter(it => { var _a, _b, _c, _d, _e; return ((_b = (_a = it.config) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.contentType) ? (!!((_e = (_d = (_c = it.config) === null || _c === void 0 ? void 0 : _c.req) === null || _d === void 0 ? void 0 : _d.contentType) === null || _e === void 0 ? void 0 : _e.find(sit => rr.reqHasContentTypeHeader(sit)))) : true; }) .filter(it => { var _a, _b, _c, _d, _e; return ((_b = (_a = it.config) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.accept) ? (!!((_e = (_d = (_c = it.config) === null || _c === void 0 ? void 0 : _c.req) === null || _d === void 0 ? void 0 : _d.accept) === null || _e === void 0 ? void 0 : _e.find(sit => rr.reqHasAcceptHeader(sit)))) : true; }); if (methods[0]) { const it = methods[0]; const paramTypes = ReflectUtils.getParameterTypes(moduleInstance, it.propertyKey); const injects = getInject(moduleInstance, it.propertyKey); const validIndexs = getValidIndex(moduleInstance, it.propertyKey); if (injects) { const isJson = injects.find(it => { var _a; return ((_a = it.config) === null || _a === void 0 ? void 0 : _a.situationType) === UrlMappingSituationType.REQ_JSON_BODY; }); const isFormUrl = injects.find(it => { var _a; return ((_a = it.config) === null || _a === void 0 ? void 0 : _a.situationType) === UrlMappingSituationType.REQ_FORM_URL_BODY; }); const isTransactionManager = injects.find(it => { var _a; return ((_a = it.config) === null || _a === void 0 ? void 0 : _a.situationType) === InjectSituationType.TransactionManager; }); const siturationContainers = new SituationTypeContainers(); if (isJson) { let data = yield rr.reqBodyJsonData(); if (isJson.type) { data = Object.assign(new isJson.type(), data); } if (validIndexs.includes(isJson.index)) { const inValid = execValidationInValid(data); if (((_e = inValid === null || inValid === void 0 ? void 0 : inValid.length) !== null && _e !== void 0 ? _e : 0) > 0) { throw new ValidException(inValid); } } siturationContainers.push(new SituationTypeContainer({ situationType: UrlMappingSituationType.REQ_JSON_BODY, data })); } if (isFormUrl) { let data = yield rr.reqBodyFormUrlData(); if (isFormUrl.type) { data = Object.assign(new isFormUrl.type(), data); } if (validIndexs.includes(isFormUrl.index)) { const inValid = execValidationInValid(data); if (((_f = inValid === null || inValid === void 0 ? void 0 : inValid.length) !== null && _f !== void 0 ? _f : 0) > 0) { throw new ValidException(inValid); } } siturationContainers.push(new SituationTypeContainer({ situationType: UrlMappingSituationType.REQ_FORM_URL_BODY, data })); } if (isTransactionManager && isTransactionManager.type && transactionManager && transactionManager.hasTransaction(isTransactionManager.type)) { let data = yield transactionManager.getTransaction(isTransactionManager.type); if (data) { data = yield data.try(isTransactionManager.config.argument); siturationContainers.push(new SituationTypeContainer({ situationType: InjectSituationType.TransactionManager, data, index: isTransactionManager.index })); } } if (siturationContainers.length) { otherStorage.set(SituationTypeContainers, siturationContainers); } } for (const paramType of paramTypes) { if (paramType === ReqFormUrlBody) { otherStorage.set(ReqFormUrlBody, yield rr.reqBodyReqFormUrlBody()); } else if (paramType === ReqJsonBody) { otherStorage.set(ReqJsonBody, yield rr.reqBodyReqJsonBody()); } else if (paramType === URLSearchParams) { otherStorage.set(URLSearchParams, rr.reqUrlSearchParams); } else if (paramType === ReqMultipartFormBody) { otherStorage.set(ReqMultipartFormBody, rr.reqBodyMultipartFormData()); } else if (paramType === ReqHeader) { otherStorage.set(ReqHeader, rr.reqHeaderObj); } } let data = yield this.simstanceManager.executeBindParameterSimPromise({ target: moduleInstance, targetKey: it.propertyKey }, otherStorage); if ((_g = it.config) === null || _g === void 0 ? void 0 : _g.resolver) { const execute = typeof it.config.resolver === 'function' ? this.simstanceManager.getOrNewSim({ target: it.config.resolver }) : it.config.resolver; data = yield ((_h = execute === null || execute === void 0 ? void 0 : execute.resolve) === null || _h === void 0 ? void 0 : _h.call(execute, data, rr)); } const status = (_l = (_k = (_j = it.config) === null || _j === void 0 ? void 0 : _j.res) === null || _k === void 0 ? void 0 : _k.status) !== null && _l !== void 0 ? _l : HttpStatus.Ok; const headers = (_p = (_o = (_m = it.config) === null || _m === void 0 ? void 0 : _m.res) === null || _o === void 0 ? void 0 : _o.header) !== null && _p !== void 0 ? _p : {}; if ((_r = (_q = it.config) === null || _q === void 0 ? void 0 : _q.res) === null || _r === void 0 ? void 0 : _r.contentType) { headers[HttpHeaders.ContentType] = (_t = (_s = it.config) === null || _s === void 0 ? void 0 : _s.res) === null || _t === void 0 ? void 0 : _t.contentType; } if (((_x = (_w = (_v = (_u = it.config) === null || _u === void 0 ? void 0 : _u.res) === null || _v === void 0 ? void 0 : _v.contentType) === null || _w === void 0 ? void 0 : _w.toLowerCase().indexOf(Mimes.ApplicationJson.toLowerCase())) !== null && _x !== void 0 ? _x : -1) > -1) { data = JSON.stringify(data); } else if (data && typeof data === 'object') { data = JSON.stringify(data); } rr.resSetHeaders(headers); rr.resSetStatusCode(status); rr.resWrite(data); } } if (this.option.noSuchRouteEndPointMappingThrow && methods.length <= 0 && ((_y = rr.reqMethod()) === null || _y === void 0 ? void 0 : _y.toUpperCase()) !== HttpMethod.OPTIONS) { throw this.option.noSuchRouteEndPointMappingThrow(rr); } } for (const it of filter.filters.reverse()) { if (((_z = it.filter) === null || _z === void 0 ? void 0 : _z.proceedAfter) && !(yield it.filter.proceedAfter({ rr, app: this, before: it.sw, carrier: filter.carrier }))) { break; } } } catch (e) { transactionManager === null || transactionManager === void 0 ? void 0 : transactionManager.catch(e); rr.resStatusCode(e instanceof HttpError ? e.status : HttpStatus.InternalServerError); const execute = typeof this.option.globalAdvice === 'function' ? this.simstanceManager.getOrNewSim(this.option.globalAdvice) : this.option.globalAdvice; if (!execute) { rr.resEnd(); return; } if (e && typeof e === 'object') { otherStorage.set(e.constructor, e); otherStorage.set(SituationTypeContainer, new SituationTypeContainer({ situationType: ExceptionHandlerSituationType.ERROR_OBJECT, data: e })); } const target = targetExceptionHandler(execute, e); if (target) { yield this.simstanceManager.executeBindParameterSimPromise({ target: execute, targetKey: target.propertyKey }, otherStorage); } } finally { transactionManager === null || transactionManager === void 0 ? void 0 : transactionManager.finally(); } if (!rr.resIsDone()) { rr.resEnd(); } })); this.server.listen(this.option.listen.port, this.option.listen.hostname, this.option.listen.backlog, () => { var _a, _b; (_b = (_a = this.option.listen).listeningListener) === null || _b === void 0 ? void 0 : _b.call(_a, this, this.server); }); } } //# sourceMappingURL=SimpleBootHttpServer.js.map