feat: 更新sign的模块

This commit is contained in:
xion 2024-11-16 12:34:08 +08:00
parent 780d744a16
commit 926c0a09cd
8 changed files with 159 additions and 8 deletions

5
.gitignore vendored
View File

@ -3,4 +3,7 @@ src/app.config.json5
dist
.npmrc
.turbo
.turbo
https-cert.pem
https-key.pem

View File

@ -0,0 +1,35 @@
import { Route, App } from '@kevisual/router';
import { readFileSync } from 'fs';
const app = new App({
serverOptions: {
cors: {},
isHTTPS: true,
httpsKey: readFileSync('https-key.pem', 'utf8'),
httpsCert: readFileSync('https-cert.pem', 'utf-8'),
},
});
app.listen(4003, '0.0.0.0', () => {
console.log(`http://localhost:4003/api/router?path=demo&key=02`);
console.log(`http://localhost:4003/api/router?path=demo&key=01`);
console.log(`https://192.168.31.220:4003/api/router?path=demo&key=01`);
});
const route01 = new Route('demo', '01');
route01.run = async (ctx) => {
ctx.body = '01';
return ctx;
};
app.use(
'demo',
async (ctx) => {
ctx.body = '01';
return ctx;
},
{ key: '01' },
);
const route02 = new Route('demo', '02');
route02.run = async (ctx) => {
ctx.body = '02';
return ctx;
};
app.addRoute(route02);

View File

@ -0,0 +1,6 @@
import { createCert } from '@kevisual/router/sign';
import { writeFileSync } from 'fs';
const { key, cert } = createCert();
writeFileSync('https-key.pem', key);
writeFileSync('https-cert.pem', cert);

View File

@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package",
"name": "@kevisual/router",
"version": "0.0.4-alpha-8",
"version": "0.0.4",
"description": "",
"main": "dist/index.js",
"module": "dist/index.js",
@ -41,6 +41,7 @@
"url": "git+https://github.com/abearxiong/kevisual-router.git"
},
"dependencies": {
"selfsigned": "^2.4.1",
"ws": "^8.18.0"
},
"publishConfig": {
@ -54,6 +55,10 @@
"./browser": {
"import": "./dist/router-browser.js",
"require": "./dist/router-browser.js"
},
"./sign": {
"import": "./dist/router-sign.js",
"require": "./dist/router-sign.js"
}
}
}
}

View File

@ -51,4 +51,26 @@ export default [
},
plugins: [dts()],
},
{
input: 'src/sign.ts',
output: {
file: 'dist/router-sign.js',
format: 'es',
},
plugins: [
resolve({
browser: false,
}),
commonjs(),
typescript(),
],
},
{
input: 'src/sign.ts',
output: {
file: 'dist/router-sign.d.ts',
format: 'es',
},
plugins: [dts()],
},
];

View File

@ -14,6 +14,9 @@ type AppOptions<T = {}> = {
path?: string;
cors?: Cors;
handle?: any;
isHTTPS?: boolean;
httpsKey?: string;
httpsCert?: string;
};
io?: boolean;
ioOpts?: { routerHandle?: RouterHandle; routerContext?: RouteContext<T>; path?: string };

View File

@ -1,6 +1,6 @@
import http, { IncomingMessage, ServerResponse } from 'http';
import https from 'https';
import { handleServer } from './handle-server.ts';
export type Listener = (...args: any[]) => void;
export type Cors = {
@ -9,12 +9,15 @@ export type Cors = {
*/
origin?: string | undefined;
};
type ServerOpts = {
export type ServerOpts = {
/**path default `/api/router` */
path?: string;
/**handle Fn */
handle?: (msg?: { path: string; key?: string; [key: string]: any }) => any;
cors?: Cors;
isHTTPS?: boolean;
httpsKey?: string;
httpsCert?: string;
};
export const resultError = (error: string, code = 500) => {
const r = {
@ -31,10 +34,20 @@ export class Server {
private _callback: any;
private cors: Cors;
private hasOn = false;
private isHTTPS = false;
private options = {
key: '',
cert: '',
};
constructor(opts?: ServerOpts) {
this.path = opts?.path || '/api/router';
this.handle = opts?.handle;
this.cors = opts?.cors;
this.isHTTPS = opts?.isHTTPS || false;
this.options = {
key: opts?.httpsKey || '',
cert: opts?.httpsCert || '',
};
}
listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void;
listen(port: number, hostname?: string, listeningListener?: () => void): void;
@ -45,11 +58,29 @@ export class Server {
listen(handle: any, backlog?: number, listeningListener?: () => void): void;
listen(handle: any, listeningListener?: () => void): void;
listen(...args: any[]) {
this._server = http.createServer();
this._server = this.createServer();
const callback = this.createCallback();
this._server.on('request', callback);
this._server.listen(...args);
}
createServer() {
let server: http.Server | https.Server;
if (this.isHTTPS) {
if (this.options.key && this.options.cert) {
server = https.createServer({
key: this.options.key,
cert: this.options.cert,
});
console.log('https server');
return server;
} else {
console.error('https key and cert is required');
console.log('downgrade to http');
}
}
server = http.createServer();
return server;
}
setHandle(handle?: any) {
this.handle = handle;
}
@ -65,7 +96,7 @@ export class Server {
if (req.url === '/favicon.ico') {
return;
}
if (res.headersSent) {
// 程序已经在其他地方响应了
return;
@ -130,7 +161,7 @@ export class Server {
* @param listener
*/
on(listener: Listener | Listener[]) {
this._server = this._server || http.createServer();
this._server = this._server || this.createServer();
this._server.removeAllListeners('request');
this.hasOn = true;
if (Array.isArray(listener)) {

46
src/sign.ts Normal file
View File

@ -0,0 +1,46 @@
import { generate } from 'selfsigned';
type Attributes = {
name: string;
value: string;
};
type AltNames = {
type: number;
value?: string;
ip?: string;
};
export const createCert = (attrs: Attributes[] = [], altNames: AltNames[] = []) => {
let attributes = [
{ name: 'commonName', value: '*' }, // 通配符域名
{ name: 'countryName', value: 'CN' }, // 国家代码
{ name: 'stateOrProvinceName', value: 'ZheJiang' }, // 州名
{ name: 'localityName', value: 'Hangzhou' }, // 城市名
{ name: 'organizationName', value: 'Envision' }, // 组织名
{ name: 'organizationalUnitName', value: 'IT' }, // 组织单位
...attrs,
];
// attribute 根据name去重复, 后面的覆盖前面的
attributes = attributes.filter((item, index, self) => {
return self.findIndex((t) => t.name === item.name) === index;
});
const options = {
days: 365, // 证书有效期(天)
extensions: [
{
name: 'subjectAltName',
altNames: [
{ type: 2, value: '*' }, // DNS 名称
{ type: 2, value: 'localhost' }, // DNS
{ type: 7, ip: '127.0.0.1' }, // IP 地址
...altNames,
],
},
],
};
const pems = generate(attributes, options);
return {
key: pems.private,
cert: pems.cert,
};
};