/************************************************************************ * Copyright (c) 2023 sunking framework * Author : Shao * Mail : yi-shaoye@163.com * Date : 2023-01-13 * Use : http网络模块 ************************************************************************/ import http, { IncomingMessage, ServerResponse } from "http"; import https from "https"; import fs from 'fs'; import { BaseConnector } from '../base/BaseConnector'; import { HttpSocket } from './HttpSocket'; import * as Loader from '../util/loader'; import myLogger from '@wingyi8/sk-logger'; import { ServerStatus } from "../util/define"; const logger = myLogger.getLogger('sunking/http/HttpConnector'); // 计数器 let curId = 1; export class HttpConnector extends BaseConnector { /** * server实例 */ private httpServer?: http.Server | https.Server = null; /** * get通讯 */ protected routeGet: string[] = []; /** * post通讯 */ protected routePost: string[] = []; /** * 路由注册 * @param handle 路由协议 * @param count 编号 */ protected registerRoute(handle: Loader.ServerEventHandler, count: number) { this.routeConfig.push(handle.url); this.routeDes.push(handle.description); this.routeHandler.push(handle.handler); if (handle.method == 'get' || handle.method == 'all') { this.routeGet.push(handle.url); } if (handle.method == 'post' || handle.method == 'all') { this.routePost.push(handle.url); } logger.info(`读取协议处理成功! [${handle.method}] [${handle.description}] url[${handle.url}] cmd[${count}]`); } /** * 检测路由方法 * @param method 路由方法 * @param url 路由地址 */ public checkMethod(method: string, url: string) { switch (method) { case 'GET': { if (this.routeGet.indexOf(url) >= 0) { return true; } } break; case 'POST': { if (this.routePost.indexOf(url) >= 0) { return true; } } break; } return false; } /** * 协议解码 * @param data 数据包 * @returns 协议解码数据 */ protected protoDecode(client: HttpSocket, data: Buffer) { let cmd = this.routeConfig.indexOf(client.getUrl()); if (cmd < 0) { logger.error(`协议解码错误 ${client.getUrl()}`); client.closed(); } return { "cmd": cmd, "msg": data } } /** * 协议编码 * @param protocol 协议 * @param packet 数据包 */ public protoEncode(protocol: string, packet: any): Buffer { return this.msgEncode(protocol, packet); } /** * 默认编码器 * @param msg 编码数据包 */ protected encode(cmd: string, msg: any) { return Buffer.from(JSON.stringify(msg)); } /** * 开启服务器 */ public start(): Promise { if (this.httpServer) { throw new Error('Server already started'); } this._status = ServerStatus.Opening; return new Promise(rs => { // 创建服务器 if (this.type == 'https') { this.httpServer = https.createServer({ key: fs.readFileSync(this.key), cert: fs.readFileSync(this.cert), }, this.onClientConnect) } else { this.httpServer = http.createServer({}, this.onClientConnect); } // 监听端口 this.httpServer.listen(this.port, () => { this._status = ServerStatus.Opened; rs(); }) // 初始化缓存信息 this.onInitBuffer(); }); } /** * 客户端连接请求 * @param ws * @param httpReq * @returns */ private onClientConnect = (httpReq: IncomingMessage, httpRes: ServerResponse) => { logger.debug(`客户端请求 ${httpReq.url} ${httpReq.method}`); if (this.status !== ServerStatus.Opened) { httpRes.statusCode = 503; httpRes.end(); return; } // 初始化客户端状态 let httpSocket = new HttpSocket(curId++, this, httpReq, httpRes); } /** * 停止服务器 */ public stop(): void { logger.info('Stopping server...'); // 立即close,不再接受新请求 this._status = ServerStatus.Closed; this.httpServer?.close(); this.httpServer = undefined; } /** * 显示服务器信息 */ public show() { logger.info(`创建 ${this.type} 服务器 [${this.des}] ${this.type}://${this.host}:${this.port}`); } }