UNPKG

@tunframework/tun

Version:

tun framework for node with typescript

114 lines (113 loc) 4.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TunApplication = void 0; const events_1 = require("events"); const http_1 = require("http"); const symbol_js_1 = require("./constants/http/symbol.js"); const HttpError_js_1 = require("./HttpError.js"); const TunComposable_js_1 = require("./TunComposable.js"); const TunContext_js_1 = require("./TunContext.js"); const TunCookie_js_1 = require("./TunCookie.js"); class TunApplication extends events_1.EventEmitter { middleware = []; mountObj = {}; constructor() { super(); } use(fn) { Array.isArray(fn) ? this.middleware.push(...fn) : this.middleware.push(fn); return this; } mount(name, obj) { this.mountObj[name] = obj; } // unmount(name: string) { // delete this.mountObj[name]; // } callback() { return (_req, _res) => { const fn = (0, TunComposable_js_1.compose)(this.middleware); const ctx = new TunContext_js_1.TunContext(_req, _res); // 挂载收集到的属性到ctx.state上 Object.assign(ctx.state, this.mountObj); return (Promise.resolve(fn(ctx)) .catch(genError) // finish 处理 设置到 应用上下文 的数据 // body 响应内容 .then((body) => dealResponse(ctx, body)) .catch((err) => dealResponse(ctx, err))); }; } listen(option) { const server = (0, http_1.createServer)(this.callback()); server.on('error', (err) => this.emit('error', err, server)); const host = process.env.HOST ? process.env.HOST : 'localhost'; const port = process.env.PORT ? parseInt(process.env.PORT) : 3000; let _option = { host, port, // path: '/', ...(option || {}) }; server.listen(_option); // Handle listening manual: // server.on('listening', () => { // let addr = (server.address() || {}) as AddressInfo // const url = 'http://' + [addr.address, addr.port].filter(Boolean).join(':') // console.log(`app listening: ${url}`) // }) return server; } } exports.TunApplication = TunApplication; function genError(err) { if (err instanceof HttpError_js_1.HttpError) { return err; } else { return new HttpError_js_1.HttpError({ error: err }); } } async function dealResponse(ctx, _body) { const _res = ctx.res[symbol_js_1.RAW_RESPONSE]; // Return if response handled by other middleware if (_res.headersSent || _res.writableEnded) return; if (typeof _body !== 'undefined') { ctx.body = _body; } ctx.body = await ctx.body; if (ctx.body instanceof HttpError_js_1.HttpError) { ctx.res.status = ctx.body.status; ctx.body = { status: ctx.res.status, message: ctx.body.message }; } else if (ctx.body instanceof Error) { ctx.res.status = 500; ctx.body = { status: ctx.res.status, message: ctx.body.message }; } // Write response header if (!(_res.headersSent || _res.writableEnded)) { if (typeof ctx.body !== 'undefined' && typeof ctx.body === 'object' && !ctx.res.type.rawType) { ctx.res.type = { rawType: 'application/json; charset=utf-8' }; } // Set response header for collected cookies const cookies = ctx.res.cookies.map(TunCookie_js_1._stringifyTunCookie); _res.setHeader.call(_res, 'set-cookie', cookies); _res.writeHead(ctx.res.status, ctx.res.message); } // Write response body if (!_res.writableEnded) { if (ctx.body !== null && typeof ctx.body !== 'undefined') { // fixme: Shouldcheck other types. e.g. Buffer. if (typeof ctx.body === 'object') { _res.write(JSON.stringify(ctx.body)); } else { _res.write(ctx.body); } } _res.end(); } }