qyani-web 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,14 @@
1
+
2
+ ### 镜像地址
3
+ ```shell
4
+ https://registry.npmmirror.com/
5
+ ```
6
+ ### 快速开始
7
+ 1. 安装TypeScript
8
+ ```shell
9
+ npm install typescript
10
+ ```
11
+ 2. 配置tsconfig.json
12
+ ```shell
13
+ npx tsc --init
14
+ ```
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import app from "/dist/lib/app.js";
2
+ import {GroupRoute} from "./dist/lib/GroupRoute.js";
3
+ export {GroupRoute};
4
+ export default app;
package/keys/cert.pem ADDED
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDDzCCAfegAwIBAgIBATANBgkqhkiG9w0BAQsFADBLMRIwEAYDVQQDEwlsb2Nh
3
+ bGhvc3QxCzAJBgNVBAYTAkNOMRIwEAYDVQQKEwlRaWFucmVubmkxFDASBgNVBAsT
4
+ C0RldmVsb3BtZW50MB4XDTI1MDUyMTAyMjAyN1oXDTI2MDUyMTAyMjAyN1owSzES
5
+ MBAGA1UEAxMJbG9jYWxob3N0MQswCQYDVQQGEwJDTjESMBAGA1UEChMJUWlhbnJl
6
+ bm5pMRQwEgYDVQQLEwtEZXZlbG9wbWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEP
7
+ ADCCAQoCggEBAOPPt4WzRj+yDuya3nlQjkG1ZhnVIpvzUp3YUzPd/Z4eJ9e+awVY
8
+ +YcObS/1hm7A44IDGTjn9m08UzNm/PfFPqE2FM1ODLV0s6myBS/NBFc/G7UiKjbr
9
+ HItznkehX+JTqm5gLu/45B4LaUtdPEmG5CYVTQa3dwypnQi4PaGMlfxmc1xzKe/K
10
+ QDEnZ39TdTlsptSb02szYQZxHvugLKde+y82pCKg9Q/SPhb3PSJjeKg8LQTFLxmM
11
+ lwmzUNSDDn/UzLaswcxLgs6wcEv422A7cR+tPL7PJ0T0cNJ2VySU/zH3WCSGr1Xn
12
+ CFJnQwCtIZS0WQ/G5zUvM6PUpy21BoJaqhcCAwEAATANBgkqhkiG9w0BAQsFAAOC
13
+ AQEARF0DvPQGHRt3waaUhFJGPNEeKrb+uCkl1c5i25SUPdcvfpa8nt6m06souMGK
14
+ oziH6uJlt/WBwgQmVp402/nxyQhNX3SY+MBkvBZ+l3FaPKsjiotM3u3vW9K8/NXD
15
+ /A4bKPie/TwurHSp5opRp9ITr15Jo1NRjRin0h0h9of0POgwEtbizuboU0sKM96g
16
+ IIv4xAWJ31ww5jtuStB1saA05YiYnnqGhfJ02ShOcFTIstLYPXSi+wd858t+96pu
17
+ A5sy9JotEJYOCGBzmQpf9tOlDHIFOvJz6inD0HOkiVtG/AjU7mlxGgAU8qbhBRZ+
18
+ Met0g+B2/TlKNaZATdRn3jGkgQ==
19
+ -----END CERTIFICATE-----
package/keys/key.pem ADDED
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEA48+3hbNGP7IO7JreeVCOQbVmGdUim/NSndhTM939nh4n175r
3
+ BVj5hw5tL/WGbsDjggMZOOf2bTxTM2b898U+oTYUzU4MtXSzqbIFL80EVz8btSIq
4
+ Nusci3OeR6Ff4lOqbmAu7/jkHgtpS108SYbkJhVNBrd3DKmdCLg9oYyV/GZzXHMp
5
+ 78pAMSdnf1N1OWym1JvTazNhBnEe+6Asp177LzakIqD1D9I+Fvc9ImN4qDwtBMUv
6
+ GYyXCbNQ1IMOf9TMtqzBzEuCzrBwS/jbYDtxH608vs8nRPRw0nZXJJT/MfdYJIav
7
+ VecIUmdDAK0hlLRZD8bnNS8zo9SnLbUGglqqFwIDAQABAoIBAARkD15RLMRIhczI
8
+ qrYS4pMLUIWkm9n+pXPWZLrQsgqMppRGyXWdF+jNqIwZQuHlRN1Pevp4+hZz6F9K
9
+ wmByLvlY0Kt+WsoFOaXxK57BaFktewwRiwJro1gKvp0Ufq50PLTg6gwFCOc4AsEJ
10
+ nIJcSmRzhPxhUoxDbqaUNS06ckpJk+re1fYVgpdwmcLdSupTDDhzwa5hp8Kte83/
11
+ Hy5Jb+5N88CA1FTltnhiH/b8ELjvUD7aC527MLjvumN0tbYG1WmRNmLsrt04Sh4a
12
+ 9Akk/Qir+WKQJ9HVnNSZzjyuMphA/cGgDc9mrsikvQxO/BJVdnBn5UhU+XyyEQIM
13
+ eRVXEDUCgYEA9uW72s160l0YDgSSUbH1vZzrXeXFx9uc+O1aEWbTjVV5J7ln0+/T
14
+ m4O49hxiiSx09caFRGN6dp6itXFSvuB1eydxEVteNQyXmrZ2dBrMATkicQ0bEGiR
15
+ kN5eBXpj/E8dlUZYu2+OfSguhWawXd2S+Aust2xT9bonz5l7oTRSWasCgYEA7DXY
16
+ ep85tU/Q0gE+50ezMd+AMp0bBGk74hDJzYxrOo+fRwSMsdl974jjWGWN4YiJ8MiT
17
+ ywFvF4JQWM7z81QBbetAbW63o+kc2l4zgRdbm3mS/fs6nYANWbZJzVxqPgG0tIXJ
18
+ 0L8ZCcO8bykYnxp/Oah2qkiNDLtjmtt/qPcgfUUCgYA0yohxT3BMnKUxEh8rIq8V
19
+ vQDCkgfJJRcaTr3sbJ0dYkJGkSk3Mtd/MBoTXZxgEkZr6ufB6Lddt6u4uiNkNuBH
20
+ 1fYiLPQmyat85DjNuJEYTdwkahX4WzOM008tQq8wWsZLjcAZS9AeyMGxunRJjcAI
21
+ E475pUsKhqROilXZ8TMOgwKBgDSjx0uEYmrqj6HNT0RhcSjDIyGka1nvTb4SebaJ
22
+ /Xd+fENqWyRjULJp8ihH8Xd6Yys6t9z8w9IcY2V3MVxfszXYwHHiw6AOmjR728R/
23
+ /RVH4Z8iNqzU1aTRf975ImARJ0E3s4MGo0DO0xZ+tRL357Rku5U1N+HHfOoM0oVI
24
+ FYB1AoGBALBmVXYclZuJsK3ZKjh+0UNGo41SnXkNLGaykAgXU35ljAZDonTyluJx
25
+ jq98FwG7LqCiYdd8bGYvT5aIP8Rs7EsTqrIYjE179H/qHWqwrLxrcwdxUC42MeTr
26
+ bX/8jsAyoez7rzC6nXkpoQ1G3kW3YoxLE72kNErnzuA6S+NciNnb
27
+ -----END RSA PRIVATE KEY-----
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "qyani-web",
3
+ "version": "1.0.0",
4
+ "description": "Backend for the app",
5
+ "main": "index.js",
6
+ "author": "Qianrenni",
7
+ "license": "MIT",
8
+ "keywords": ["backend", "node","framework"],
9
+ "type": "module",
10
+ "dependencies": {
11
+ "busboy": "^1.6.0",
12
+ "node-forge": "^1.3.1"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "start": "tsc & node dist/index.js"
17
+ },
18
+ "devDependencies": {
19
+ "@types/busboy": "^1.5.4",
20
+ "@types/node": "^24.0.10",
21
+ "@types/node-forge": "^1.3.11",
22
+ "ts-node": "^10.9.2",
23
+ "typescript": "^5.8.3"
24
+ }
25
+ }
@@ -0,0 +1,44 @@
1
+ import http from "http";
2
+ /**
3
+ * 文件信息
4
+ * @param fieldname 字段名
5
+ * @param filename 文件名
6
+ * @param encoding 编码
7
+ * @param mimetype MIME类型
8
+ * @param data 文件数据
9
+ */
10
+ export type FileInfo = {
11
+ fieldname: string;
12
+ filename: string;
13
+ encoding: string;
14
+ mimetype: string;
15
+ data: Buffer;
16
+ };
17
+
18
+ /**
19
+ * 处理请求对象
20
+ * @param query 查询参数
21
+ * @param params 路由参数
22
+ * @param body 请求体
23
+ */
24
+ export type ProcessRequest = {
25
+ query: Record<string, string|number|boolean>,
26
+ params: Record<string, string|number|boolean>,
27
+ body:{fields:Record<string, string|number|boolean>, files:FileInfo[]},
28
+ } & http.IncomingMessage;
29
+
30
+ /**
31
+ * 中间件函数类型定义
32
+ * @param req 请求对象
33
+ * @param res 响应对象
34
+ * @return 返回一个布尔值,表示是否结束请求
35
+ */
36
+ export type Middleware = (req: http.IncomingMessage, res: http.ServerResponse) => boolean|Promise<boolean>| undefined;
37
+
38
+ /**
39
+ * 请求处理函数类型定义
40
+ * @param req 请求对象
41
+ * @param res 响应对象
42
+ * @return 返回一个布尔值,表示是否结束请求
43
+ */
44
+ export type Handler = (req: http.IncomingMessage, res: http.ServerResponse) =>boolean|Promise<boolean>|undefined;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ // controllers/homeController.js
3
+ import http from "http";
4
+
5
+
6
+ /**
7
+ * 首页
8
+ * @param req
9
+ * @param res
10
+ */
11
+ export const index = (req:http.IncomingMessage, res:http.ServerResponse) => {
12
+ const request = req as ProcessRequest;
13
+ res.writeHead(200, { 'Content-Type': 'application/json' });
14
+ res.end(JSON.stringify({
15
+ message: 'Welcome to Qianrenni\'s WebApp FrameWork',
16
+ query: Object.fromEntries((request as any).query??{}),
17
+ params: (request as any).params??{}
18
+ }));
19
+ return true;
20
+ };
21
+
22
+ /**
23
+ * 用户详情
24
+ * @param req
25
+ * @param res
26
+ */
27
+ export const userDetail = (req:http.IncomingMessage, res:http.ServerResponse) => {
28
+ const request = req as ProcessRequest;
29
+
30
+ // 确保 query 存在并转换为 Record 类型
31
+ const queryParams = request.query
32
+ ?Object.entries(request.query)
33
+ : {};
34
+
35
+ res.writeHead(200, { 'Content-Type': 'application/json' });
36
+ res.end(JSON.stringify({
37
+ id: request.params?.id,
38
+ query: queryParams
39
+ }));
40
+
41
+ return true;
42
+ };
43
+
44
+
45
+
46
+
47
+ import fs from 'fs/promises';
48
+ import path from 'path';
49
+ import { fileURLToPath } from 'url';
50
+ import {ProcessRequest} from "../config/type";
51
+
52
+ // 替换 __dirname
53
+ const __filename = fileURLToPath(import.meta.url);
54
+ const __dirname = path.dirname(__filename);
55
+
56
+ // 确保 public 目录存在
57
+ const PUBLIC_DIR = path.join(__dirname, '../public');
58
+
59
+ fs.access(PUBLIC_DIR)
60
+ .then(() => {})
61
+ .catch(async () => {
62
+ await fs.mkdir(PUBLIC_DIR, { recursive: true }); // 添加 recursive 避免多级目录问题
63
+ });
64
+
65
+ /**
66
+ * 上传文件
67
+ * @param req
68
+ * @param res
69
+ */
70
+ export const uploadFiles = async (req:http.IncomingMessage, res:http.ServerResponse) => {
71
+ const request = req as ProcessRequest;
72
+ const data = request.body;
73
+ const savedFiles = [];
74
+ const keys = Object.keys(data?.fields);
75
+
76
+ if (data?.files) {
77
+ for (const file of data.files) {
78
+ const filePath = path.join(PUBLIC_DIR, file.filename);
79
+ await fs.writeFile(filePath, file.data);
80
+ savedFiles.push(file.filename);
81
+ console.log(`文件已保存至: ${filePath}`);
82
+ }
83
+ }
84
+
85
+ res.writeHead(200, { 'Content-Type': 'application/json' });
86
+ res.end(JSON.stringify({
87
+ status: 'success',
88
+ message: `${savedFiles.length} 个文件 ${keys.length} 参数上传成功`,
89
+ files: data?.files?.map(f => f.filename),
90
+ fields: keys
91
+ }));
92
+ return true;
93
+ };
package/src/index.ts ADDED
@@ -0,0 +1,20 @@
1
+ // index.js
2
+ import ('./routes/index.js')
3
+
4
+ import app from './lib/app.js'
5
+
6
+ const port = 443;
7
+ // 捕获未处理的异常
8
+ process.on('uncaughtException', (err) => {
9
+ console.error('[FATAL] Uncaught Exception:', err);
10
+ setTimeout(() => process.exit(1), 1000); // 安全退出
11
+ });
12
+
13
+ process.on('unhandledRejection', (reason, promise) => {
14
+ console.error('[WARNING] Unhandled Rejection at:', reason,'Promise', promise);
15
+ setTimeout(() => process.exit(1), 1000);
16
+
17
+ });
18
+ app.listen(port, () => {
19
+ console.log(`Server running on https://localhost:${port}`);
20
+ });
@@ -0,0 +1,153 @@
1
+ import http from "http";
2
+
3
+ /**
4
+ * 中间件函数类型定义
5
+ * @param req 请求对象
6
+ * @param res 响应对象
7
+ * @return 返回一个布尔值,表示是否结束请求
8
+ */
9
+ type Middleware = (req: http.IncomingMessage, res: http.ServerResponse) => boolean|Promise<boolean>| undefined;
10
+
11
+ /**
12
+ * 请求处理函数类型定义
13
+ * @param req 请求对象
14
+ * @param res 响应对象
15
+ * @return 返回一个布尔值,表示是否结束请求
16
+ */
17
+ type Handler = (req: http.IncomingMessage, res: http.ServerResponse) => boolean|Promise<boolean>|undefined;
18
+
19
+
20
+ /**
21
+ * GroupRoute 类用于组织和管理一组具有共同前缀的 HTTP 路由。
22
+ * 支持在请求处理前后添加中间件,并支持链式调用。
23
+ */
24
+ export class GroupRoute {
25
+ // 在请求处理前执行的中间件列表
26
+ private beforeRequestMiddleWares: Middleware[] = [];
27
+
28
+ // 在请求处理后执行的中间件列表
29
+ private afterRequestMiddleWares: Middleware[] = [];
30
+
31
+ // 注册的路由列表,包含 HTTP 方法、URL 和处理链
32
+ private routes: { method: string; url: string; chain: Middleware[] }[] = [];
33
+
34
+ /**
35
+ * 构造函数
36
+ * @param prefix 路由组的前缀,例如 "/api"
37
+ */
38
+ constructor(private readonly prefix: string) {}
39
+
40
+ /**
41
+ * 添加一个在请求处理前执行的中间件
42
+ * @param middleware 中间件函数
43
+ * @returns 返回当前 GroupRoute 实例,支持链式调用
44
+ */
45
+ beforeRequest(middleware: Middleware): this {
46
+ this.beforeRequestMiddleWares.push(middleware);
47
+ return this;
48
+ }
49
+
50
+ /**
51
+ * 添加一个在请求处理后执行的中间件
52
+ * @param middleware 中间件函数
53
+ * @returns 返回当前 GroupRoute 实例,支持链式调用
54
+ */
55
+ afterRequest(middleware: Middleware): this {
56
+ this.afterRequestMiddleWares.push(middleware);
57
+ return this;
58
+ }
59
+
60
+ /**
61
+ * 注册一个 GET 请求路由
62
+ * @param url 路由路径
63
+ * @param handler 请求处理函数
64
+ * @param beforeRequest 在处理函数前执行的中间件数组
65
+ * @param afterRequest 在处理函数后执行的中间件数组
66
+ * @returns 返回当前 GroupRoute 实例,支持链式调用
67
+ */
68
+ get(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
69
+ this._register('GET', this.prefix + url, handler, beforeRequest, afterRequest);
70
+ return this;
71
+ }
72
+
73
+ /**
74
+ * 注册一个 POST 请求路由
75
+ * @param url 路由路径
76
+ * @param handler 请求处理函数
77
+ * @param beforeRequest 在处理函数前执行的中间件数组
78
+ * @param afterRequest 在处理函数后执行的中间件数组
79
+ * @returns 返回当前 GroupRoute 实例,支持链式调用
80
+ */
81
+ post(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
82
+ this._register('POST', this.prefix + url, handler, beforeRequest, afterRequest);
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ * 注册一个 PUT 请求路由
88
+ * @param url 路由路径
89
+ * @param handler 请求处理函数
90
+ * @param beforeRequest 在处理函数前执行的中间件数组
91
+ * @param afterRequest 在处理函数后执行的中间件数组
92
+ * @returns 返回当前 GroupRoute 实例,支持链式调用
93
+ */
94
+ put(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
95
+ this._register('PUT', this.prefix + url, handler, beforeRequest, afterRequest);
96
+ return this;
97
+ }
98
+
99
+ /**
100
+ * 注册一个 DELETE 请求路由
101
+ * @param url 路由路径
102
+ * @param handler 请求处理函数
103
+ * @param beforeRequest 在处理函数前执行的中间件数组
104
+ * @param afterRequest 在处理函数后执行的中间件数组
105
+ * @returns 返回当前 GroupRoute 实例,支持链式调用
106
+ */
107
+ delete(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
108
+ this._register('DELETE', this.prefix + url, handler, beforeRequest, afterRequest);
109
+ return this;
110
+ }
111
+
112
+ /**
113
+ * 通用方法,用于注册任意 HTTP 方法的路由
114
+ * @param method HTTP 方法,如 'GET', 'POST' 等
115
+ * @param url 路由路径
116
+ * @param handler 请求处理函数
117
+ * @param beforeRequest 在处理函数前执行的中间件数组
118
+ * @param afterRequest 在处理函数后执行的中间件数组
119
+ */
120
+ request(method: string, url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
121
+ this._register(method, url, handler, beforeRequest, afterRequest);
122
+ return this;
123
+ }
124
+
125
+ /**
126
+ * 内部方法,用于将路由信息注册到路由列表中
127
+ * @param method HTTP 方法
128
+ * @param url 路由路径
129
+ * @param handler 请求处理函数
130
+ * @param beforeRequest 在处理函数前执行的中间件数组
131
+ * @param afterRequest 在处理函数后执行的中间件数组
132
+ */
133
+ private _register(method: string, url: string, handler: Handler, beforeRequest: Middleware[], afterRequest: Middleware[]): void {
134
+ // 构建完整的中间件链:beforeRequestMiddleWares + beforeRequest + handler + afterRequest + afterRequestMiddleWares
135
+ const chain: Middleware[] = [
136
+ ...this.beforeRequestMiddleWares,
137
+ ...beforeRequest,
138
+ handler,
139
+ ...afterRequest,
140
+ ...this.afterRequestMiddleWares,
141
+ ];
142
+
143
+ this.routes.push({ method, url, chain });
144
+ }
145
+
146
+ /**
147
+ * 获取当前路由组的所有路由信息(可用于调试或注册到框架中)
148
+ * @returns 路由列表
149
+ */
150
+ getRoutes(): { method: string; url: string; chain: Middleware[] }[] {
151
+ return this.routes;
152
+ }
153
+ }
package/src/lib/app.ts ADDED
@@ -0,0 +1,232 @@
1
+ // app.js
2
+ import https from 'https';
3
+ import url from 'url';
4
+ import certs from '../utils/certs.js';
5
+ import {GroupRoute} from "./GroupRoute";
6
+ import * as http from "http";
7
+ import {Handler, Middleware} from "../config/type";
8
+
9
+
10
+ class WebApp {
11
+ private routes: { method: string; url: string; chain: Middleware[] }[]= [];
12
+ private beforeRequestMiddleWares: Middleware[]= [];
13
+ private afterRequestMiddleWares: Middleware[]= [];
14
+ constructor() {}
15
+
16
+ /**
17
+ * 添加一个前置中间件
18
+ * @param middleware 中间件函数
19
+ * @returns 返回当前 WebApp 实例,支持链式调用
20
+ */
21
+ beforeRequest(middleware: Middleware): this {
22
+ if (typeof middleware !== 'function') {
23
+ throw new Error('Middleware must be a function');
24
+ }
25
+ if (this.beforeRequestMiddleWares.includes(middleware)){
26
+ throw new Error('Middleware already exists');
27
+ }
28
+ this.beforeRequestMiddleWares.push(middleware);
29
+ return this;
30
+ }
31
+
32
+ /**
33
+ * 添加一个后置中间件
34
+ * @param middleware 中间件函数
35
+ * @returns 返回当前 WebApp 实例,支持链式调用
36
+ */
37
+ afterRequest(middleware: Middleware): this {
38
+ if (typeof middleware !== 'function') {
39
+ throw new Error('Middleware must be a function');
40
+ }
41
+ if (this.afterRequestMiddleWares.includes(middleware)){
42
+ throw new Error('Middleware already exists');
43
+ }
44
+ this.afterRequestMiddleWares.push(middleware);
45
+ return this;
46
+ }
47
+ /**
48
+ * 注册一个路由
49
+ * @param method HTTP 方法,如 'GET', 'POST' 等
50
+ * @param url 路由路径
51
+ * @param handler 请求处理函数
52
+ * @param beforeRequest 在处理函数前执行的中间件数组
53
+ * @param afterRequest 在处理函数后执行的中间件数组
54
+ * @returns 返回当前 WebApp 实例,支持链式调用
55
+ */
56
+ request(method: string, url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
57
+ this._register(method, url, handler, beforeRequest, afterRequest);
58
+ return this;
59
+ }
60
+ /**
61
+ * 注册一个 GET 请求路由
62
+ * @param url 路由路径
63
+ * @param handler 请求处理函数
64
+ * @param beforeRequest 在处理函数前执行的中间件数组
65
+ * @param afterRequest 在处理函数后执行的中间件数组
66
+ * @returns 返回当前 WebApp 实例,支持链式调用
67
+ */
68
+ get(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
69
+ this._register('GET', url, handler, beforeRequest, afterRequest);
70
+ return this;
71
+ }
72
+
73
+ /**
74
+ * 注册一个 POST 请求路由
75
+ * @param url 路由路径
76
+ * @param handler 请求处理函数
77
+ * @param beforeRequest 在处理函数前执行的中间件数组
78
+ * @param afterRequest 在处理函数后执行的中间件数组
79
+ * @returns 返回当前 WebApp 实例,支持链式调用
80
+ */
81
+ post(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
82
+ this._register('POST', url, handler, beforeRequest, afterRequest);
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ * 注册一个 PUT 请求路由
88
+ * @param url 路由路径
89
+ * @param handler 请求处理函数
90
+ * @param beforeRequest 在处理函数前执行的中间件数组
91
+ * @param afterRequest 在处理函数后执行的中间件数组
92
+ * @returns 返回当前 WebApp 实例,支持链式调用
93
+ */
94
+ put(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
95
+ this._register('PUT', url, handler, beforeRequest, afterRequest);
96
+ return this;
97
+ }
98
+
99
+ /**
100
+ * 注册一个 DELETE 请求路由
101
+ * @param url 路由路径
102
+ * @param handler 请求处理函数
103
+ * @param beforeRequest 在处理函数前执行的中间件数组
104
+ * @param afterRequest 在处理函数后执行的中间件数组
105
+ * @returns 返回当前 WebApp 实例,支持链式调用
106
+ */
107
+ delete(url: string, handler: Handler, beforeRequest: Middleware[] = [], afterRequest: Middleware[] = []): this {
108
+ this._register('DELETE', url, handler, beforeRequest, afterRequest);
109
+ return this;
110
+ }
111
+
112
+ /**
113
+ * 内部方法,用于注册路由
114
+ * @param method HTTP 方法
115
+ * @param url 路由路径
116
+ * @param handler 请求处理函数
117
+ * @param beforeRequest 在处理函数前执行的中间件数组
118
+ * @param afterRequest 在处理函数后执行的中间件数组
119
+ */
120
+ private _register(method: string, url: string, handler: Handler, beforeRequest: Middleware[], afterRequest: Middleware[]): void {
121
+ // 构建完整的中间件链:beforeRequest + handler + afterRequest
122
+ const chain = [...beforeRequest, handler, ...afterRequest];
123
+ this.routes.push({ method, url, chain });
124
+ }
125
+ /**
126
+ * 注册一个路由组
127
+ * @param groupRoute 路由组实例
128
+ * @returns 返回当前 WebApp 实例,支持链式调用
129
+ */
130
+ registerGroupRoute(groupRoute: GroupRoute): this {
131
+ this.routes.push(...groupRoute.getRoutes());
132
+ return this;
133
+ }
134
+
135
+ /**
136
+ * 匹配路由参数
137
+ * @param routePath 路由路径
138
+ * @param requestPath 请求路径
139
+ * @returns 匹配的参数对象
140
+ */
141
+ matchRoute(routePath: string, requestPath: string):Record<string, string> | null {
142
+ const routeParts = routePath.split('/');
143
+ const requestParts = requestPath.split('/');
144
+
145
+ if (routeParts.length !== requestParts.length) return null;
146
+
147
+ const params: Record<string, string> = {};
148
+ for (let i = 0; i < routeParts.length; i++) {
149
+ if (routeParts[i] !== requestParts[i] && !routeParts[i].startsWith(':')) {
150
+ return null;
151
+ }
152
+ if (routeParts[i].startsWith(':')) {
153
+ const paramName = routeParts[i].slice(1);
154
+ params[paramName] = requestParts[i];
155
+ }
156
+ }
157
+
158
+ return params;
159
+ }
160
+
161
+ /**
162
+ * 启动服务器
163
+ * @param port 端口号
164
+ * @param callback 回调函数
165
+ */
166
+ listen(port: number, callback: () => void): void {
167
+ const server = https.createServer(certs,async (req:http.IncomingMessage, res:http.ServerResponse) => {
168
+ const parsedUrl = new url.URL(req.url??'', `http://${req.headers.host}`);
169
+ const path = parsedUrl.pathname;
170
+ const method = req.method;
171
+
172
+ // 标记是否结束处理
173
+ let handled : boolean|Promise<boolean>|undefined= false;
174
+ try {
175
+ //执行前置中间件
176
+ for (const mw of this.beforeRequestMiddleWares) {
177
+ if (handled!==true) handled = await mw(req, res);
178
+ }
179
+ if (handled) return;
180
+ // 查找匹配的路由
181
+ let matchedRoute: { method: string; url: string; chain: Middleware[] } | null = null
182
+ let params:Record<string, string> | null = null;
183
+
184
+ for (let route of this.routes) {
185
+ if (route.method === method) {
186
+ params=this.matchRoute(route.url, path);
187
+ if (params) {
188
+ matchedRoute = route;
189
+ break;
190
+ }
191
+ }
192
+ }
193
+ if(params&&matchedRoute){
194
+ // 设置请求参数
195
+ (req as any).query = parsedUrl.searchParams;
196
+ (req as any).params = params;
197
+ for (const mw of matchedRoute.chain) {
198
+ if (!handled) handled = await mw(req, res);
199
+ }
200
+ }else{
201
+ // 404
202
+ res.writeHead(404, {'Content-Type': 'application/json'});
203
+ res.end(JSON.stringify({error: 'Not Found'}));
204
+ }
205
+ }catch (error:unknown){
206
+ // 500
207
+ res.writeHead(500, {'Content-Type': 'application/json'});
208
+ if(error instanceof Error){
209
+ res.end(JSON.stringify({
210
+ error: 'Internal Server Error',
211
+ message: error.message,
212
+ }));
213
+ console.log(error.stack);
214
+ }else{
215
+ res.end(JSON.stringify({
216
+ error: 'Internal Server Error',
217
+ message: 'An unknown error occurred.',
218
+ }));
219
+ }
220
+ }finally {
221
+ //执行后置中间件
222
+ for (const mw of this.afterRequestMiddleWares) {
223
+ if (!handled) handled = await mw(req, res);
224
+ }
225
+ }
226
+ });
227
+ server.listen(port, callback);
228
+ }
229
+ }
230
+
231
+ const app= new WebApp();
232
+ export default app;