npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

server_one

v3.4.2

Published

A lightweight frame of the NodeJS

Downloads

150

Readme

server_one

install

npm install server_one

支持Node版本

v14.14.0 以上

版本改动

version 3.3.3 --> version 3.3.4 文档改动
version 3.3.4 --> version 3.3.5 thread_pool类被废弃,改用worker_pool类,并且Jsonwebtoken类和Encryption也被重写
version 3.3.5 --> version 3.3.6 添加WebSocket类用于处理websocket连接
version 3.3.6 --> version 3.3.7 websocket类的bug修复
version 3.3.7 --> version 3.3.8 修复Encryption类的bug
version 3.3.8 --> version 3.3.9 废弃Server_one.body_parse和Server_one.form_data中间件,全部改用Server_one.middleware.body_parse中间件,并且修复了一些bug,并且提供了Server_one.middleware来专门存放内置中间件
version 3.3.9 --> version 3.3.10 废弃Server_one.Thread_pool类 , Encryption类添加random_str静态方法用于获取随机指定长度的字符串
version 3.3.9 --> version 3.3.11 些许改动
version 3.3.12 --> version 3.3.13 为Encryption类的所有函数提供了静态的同步方法
version 3.3.13 --> version 3.3.14 修改了Encryption类的加密解密函数的实现
version 3.3.14 --> version 3.3.15 修复了body_parse的一个小bug
version 3.3.15 --> version 3.3.16 修复了Jsonwebtoken类的一个小bug,给thread.execute函数添加了一个全局__worker_handle__变量,用于获取子线程对象
version 3.3.16 --> version 3.4.1 修改了Websocket的api
version 3.4.1 --> version 3.4.2 部分修改

目录信息

server_one 
----encryption
    ----encryption.js # 加密解密类
----jsonwebtoken
    ----jsonwebtoken.js # server_one_jwt类
----middleware
	----body_parse
		----form_data.js # 解析form_data类型的请求数据,由body_parse中间件调用
		----body_parse.js # body_parse中间件,用于处理post请求的数据
		----x_www_form_urlencoded.js # 解析post请求的数据,由body_parse中间件调用
	----middleware.js # 框架内置中间件模块
----mysql
    ----mysql.js # 数据库操作的简单封装,依赖于mysql包
----thread
    ----worker_pool.js # 线程池的封装,操作更加简单,用户可以自行查看调用方式
    ----worker_thread_file.js # 线程池实现逻辑
----websocket
	----websocket.js # websocket操作的简易封装
----algorithm.js # 一些算法的封装,暂时没有被使用
----README.md # 说明文档
----router.js # 核心类Router类
----server_one.js # 核心类Server_one类
    

Introduction

这是我仿照express写的一个简单服务器框架,主要用作学习,还额外添加了一些我认为有用的东西。

Server_one 类

构造器

new Server_one([option]) 当我们传入第一个参数时,启用https模块,需要ssl证书的信息。

基本操作

这是框架的主类,所有的功能都是通过它暴露出来的。同时它也是Router类的子类,详情可以查看 源代码:server_one/server_one.js 文件。它是整个框架实现web服务的起点,我们可以先创建一个它的对象。

// 引入Server_one类
const Server_one = require('server_one');
// 创建实例
const app = new Server_one();

// 调用listen方法,开启服务 , 第一个参数是服务端口号,第二个则是开启后的回调函数
app.listen(9898 , () =>
{
    console.log('服务器端口号 : 9898');
});

这样,一个web服务就启动了。

接下来是路由的添加,Router类提供了3种添加路由路由的方式,use , get , post , err ,而我们的Server_one类继承了Router所以可以直接使用这四个函数,其中use函数添加的路由会无视请求方法的不同,直接进行路由匹配,若符合条件则加入执行队列。

对于https服务的创建,只需要在构造器中传入一个对象 {key : "xxx" , cert : "xxx"} 那么Server_one就会创建https服务器了。

// 加入路由(路由前面不用带"/")
app.use("test",(req,resp,next) =>
{
    resp.send("test use function");
});
// 传入Server_one.Router.ANY_PATH与不传第一个参数一样,即第一个参数默认是Server_one.Router.ANY_PATH
app.use(Server_one.Router.ANY_PATH,(req,resp,next)=>
{
    console.log("any");
    next();
});
app.use(Server_one.Router.ANY_PATH,Server_one.Router.ANY_METHOD,(req,resp,next)=>
{
    console.log("any");
    next();
});
// 直接传入一个或多个函数
app.use((req,resp,next) =>
{
    next();
},(req,resp,next) =>
{
    resp.send("use function");
});

这样我们就可以通过 http://localhost:9898/test 和 http://localhost:9898 来分别触发这几个函数了。

请求数据

其中回调函数中的req是Server_one.Request的对象实例,它继承了http.IncomingMessage,所以可以通过它获取到请求的信息;并且Server_one内置了两个插件用于解析post请求的数据

/** 获取post请求参数 */
// app.use(Server_one.body_parse()); // 废弃

/** 处理formData数据 */
// app.use(Server_one.form_data()); // 废弃

/* 处理post请求的数据,并将它挂载在req.body上 */
app.use(Server_one.middleware.body_parse());

// 这两个插件解析的数据都会放在req.body对象中 , get请求的数据会被自动解析到req.query对象中

回调函数中的resp是Server_one.Response的对象实例,它继承了http.Response,可以通过它发送反馈信息。

回调函数中的next其实是一个函数,在调用它之前,本次请求会被卡在该函数中(类似于被阻塞),每次调用next会让本次请求继续执行下一步函数的调用,所以,请在适当的时候调用next放行吧。同时next也可以接收一个参数,当参数为"next"时,则会跳过本次添加的所有函数:

app.use(Server_one.Router.ANY_PATH,Server_one.Router.ANY_METHOD,(req,resp,next)=>
{
    console.log(req.body); // 查看post请求数据,前提是挂载了Server_one.middleware.body_parse中间件
    console.log(req.query); // 查看get请求数据,无需挂载任何中间件,框架内部自动处理
    next();
},(req,resp,next)=>
{
    console.log("2");
    next("next"); // 会导致本次请求直接进入下一个符合条件的RouterExecute
},(req,resp,next)=>
{
    console.log("3");
    next();
});
app.use(Server_one.Router.ANY_PATH,Server_one.Router.ANY_METHOD,(req,resp,next)=>
{
    console.log("4");
    next();
});
// 结果输出 : 1 , 2 , 4 我们可以看到3没有被输出 , 这是因为我们传入"next"参数跳过了它的执行

当然了,next也可以接受其他非"next"类型的参数,具体看app.err函数的介绍

app.use([path : string],[method : string],...calls)函数

同时use也接受另一个路由作为参数:

app.use("router" , new Server_one.Router());
// 或
app.use(new Server_one.Router("router"));
// 或
app.use(new Server_one.Router());
// 或
app.use("api","GET",(req,resp,next) => 
{
    next();
}) // 这里可以直接用"GET"不过,还是推荐使用框架提供的Server_one.Router.GET_METHOD
// 同样的 在匹配通用方法时推荐Server_one.Router.ANY_METHOD或不写post请求则使用Server_one.Router.POST_METHOD

app.get([path : string],...calls) , app.post([path : string],...calls)函数

至于 post 和 get 除了不用传入请求方式外,基本与use函数没有什么不同 , 毕竟也是通过use实现的。

app.err(...calls)函数

err函数则比较特殊,它只接受一个或多个函数作为参数,会在任意一个next("xxx")参数列表中被传入非空或"next"时被链式地调用(当前路由 -> 主路由):

// err 就是next("xxx")传入的数据
app.err((err,req,resp,next) => 
{
	console.log(err); // 输出:"xxx"
});

Server_one.Worker_pool类

线程池类,用于创建一个线程池。

// 线程数量
const limit = 5;
// 创建线程池对象
const pool = new Server_one.Worker_pool(limit/*线程数量 , 可以不选 , 默认为2*/);

pool.get_thread(void) 函数

该函数返回一个Promise<Worker_thread>。

pool.get_thread()
.then(async (worker) => 
{
    // 调用worker对象的execute方法开启多线程
    /*
    函数原型 : Worker_thread.prototype.execute( call:()=>any , [data : Object] , [lib : Array<string>]);
    call 是线程要执行的函数
    data 是执行时的上下文中的数据
    lib 是执行时使用的库的路径数组
    注意,execute中的回调函数是多线程执行的,所以在这里它无法访问到该作用域的数据,必须在data中声明。
    这里调用第三方库或标准库时,必须在lib中表示
    */
    const count = 100;
    const no_count = 200;
    const data = await worker.execute(() => 
    {
        // 可以获取到子线程的对象
        __worker_handle__.postMessage("");
        // 这里count可以修改与外界的count无关
        count += 1;
        // 由于我们在lib里面加入了fs和path所以这里也可以调用
        const stream = fs.createStream(path.join(__dirname , "./test.json"));
        console.log(count); // 101 正常输出
        // console.log(no_count); // error : no_count is not definition 这里无法访问到外界的no_count数据
        return {name : "test end"}; // 返回值会作为execute的放回值被返回
    } , {count} , ["fs" , "path"]);
    
    console.log(data); // {name : "test end"}
    // 之后线程会自动被放回线程池,等待下一次使用
})

pool.destroy_pool(void)函数

用于销毁当前线程池。

Server.Mysql类

它依赖于mysql包,我们在创建这个类的实例时,它会判断是否安装了这个包,若没有则抛出异常,若安装了,则可以正常使用。

依赖包 : npm install mysql

const option = 
{
    user : "root", // mysql用户名
    password : "123456", // mysql用户密码
    database : "xiaojiangbuhuia", // 连接的数据库
    host : "127.0.0.1", // 主机IP
    port : "3306", // 数据库端口号
}
const mysql = new Server_one.Mysql(option); // 创建mysql对象

mysql.query(sql : string , [data : Array])函数

mysql.query("select * from xx_table where id=?" , [1])
.then((value) => 
{
    console.log(value);
});

async function test ()
{
	const data = await mysql.query("select * from xx_table where id=?" , [1]);
}

mysql.query会执行一条sql语句,并且支持预匹配(即以 ? 来替代某些数据,这样可以有效防止sql注入),并返回一个Promise。

第一个参数是sql语句,支持预匹配。第二个参数是一个数组,用来传递执行预匹配的数据,示例表示的意思是,查找xx_table(你的表名)中id为1的数据的所有字段。它会返回一个promise所以也支持Async/Await语法,结果会在promise中被返回。

mysql.begin_transaction(void)函数

下面是一般使用方法 :

async function test ()
{
    const connect = await mysql.begin_transaction(); // 会返回一个Transaction类的对象,用于执行事务
	try
    {
    	let data1 = await connect.query("insert into xx_table (xx,xx) values (?,?)",[1,2]); // 事务语句1
    	let data2 = await connect.query("insert into xx_table (xx,xx) values (?,?)",[1,2]); // 事务语句2
        connect.commit(); // 提交事务,不然插入等操作不会被真正执行
    }
    catch (err)
    {
        // 出现异常 , 事务回滚
        connect.rollback();
    }
    finally
    {
        // 释放资源
        connect.release();
    }
}

Server_one.Jsonwebtoken 类

提供了两个静态方法用于token的简单生成和解析。

Server_one.Jsonwebtoken.generate(key : string, data : any , [options : {coding:string,effectiveTime:number}])

该函数用于生成token :

async function test ()
{
    const token = await Server_one.Jsonwebtoken.generate("my_key" , {name : "mr.jiang" , age : 14},{effective : 1000*60*60 , coding : "base64"});
    console.log(token);
    /*
  eyJhbGdvcml0aG0iOiJiYXNlNjQifQ==.eyJuYW1lIjoibXIuamlhbmciLCJhZ2UiOjE0fQ==.eyJlZmZlY3RpdmVUaW1lIjotMSwiY3JlYXRlVGltZSI6MTY0NTE5NTkyODM
2OCwia2V5IjoibXlfa2V5In0=
    */
}

第一个参数是 它相当于一把钥匙,可以是任意字符串,在解析时需要它。

第二个参数是要保存的 数据 可以是任何可序列化的数据

第三个参数是 配置对象 可以不写,effective token的有效表示时间,默认永久 , coding 表示编码方式,可以不选,若设置了,则之后解码时也需要设置相同的编码。

Server_one.Jsonwebtoken.parse(token:string,key:string,[options:{coding:string}])

该函数用于解析token :

async function test ()
{
    const data = await Server_one.Jsonwebtoken.parse(` eyJhbGdvcml0aG0iOiJiYXNlNjQifQ==.eyJuYW1lIjoibXIuamlhbmciLCJhZ2UiOjE0fQ==.eyJlZmZlY3RpdmVUaW1lIjotMSwiY3JlYXRlVGltZSI6MTY0NTE5NTkyODM
2OCwia2V5IjoibXlfa2V5In0=` , "my_key" , {coding : "base64"});
    console.log(data); // {name : "mr.jiang" , age : 14}
}

第一个参数是 token 就是我们生成的token

第二个参数是 生成时指定的键

第三个参数是 配置对象 可以不写coding 表示编码方式,可以不选,若设置了,则之前编码时也需要设置相同的编码。

这两个函数都会在第一次被调用时创建一个Server_one.Thread_pool对象,它们的解析与生成也是在其他线程进行的,所以不需要担心会阻塞主线程。

Server_one.Encryption类

该类提供了部分多线程加密方法。以及同步加密解密的方法

// 该类提供了一个变量用于控制是否采用相对不可读的加密方式,默认关闭
Server_one.Encryption.complex = true; // 开启该方式

const md5 = await Server_one.Encryption.md5("149847ababab"); // md5加密
const md5_sync = Server_one.Encryption.md5_synchronize("149847ababab"); // 同步md5加密
const obj_cry = await Server_one.Encryption.encryption({name : "小江不会啊"}); // 可逆的简单加密
const obj_cry_sync = Server_one.Encryption.encryption_synchronize({name : "小江不会啊"}); // 同步可逆的简单加密
const obj = await Server_one.Encryption.decryption(obj_cry); // 对上一个方法加密的数据进行解密
const obj_sync = Server_one.Encryption.decryption_synchronize(obj_cry); // 同步对上一个方法加密的数据进行解密

// 获取指定长度的随机字符串,第一个参数是字符串的模式默认"any" , 第二个参数则是字符串长度,默认6
/*
模式有 :
"any" 大小写字母和数字
"number" 仅数字
"any_letter" 仅大小写字母
"lower_letter" 仅小写字母
"uppercase_letter" 仅大写字母
"number_lower_letter" 数字和小写字母
"number_uppercase_letter" 数字和大写字母
*/
const random_string = await  Server_one.Encryption.random_str("any" , 5);
const random_string_sync = Server_one.Encryption.random_str_synchronize("any" , 5);

Server_one.Websocket类

用于websocket连接的处理

操作演示

const websocket = new Server_one.WebSocket(); // 创建一个websocket实例

// 连接成功的回调 , 回调中会有一个socket对象
websocket.connect((socket) =>
{
    // 接受消息的回调,它是一个Buffer对象
    socket.on_message((v) =>
    {
        console.log(v.toString());
    });
    // 连接结束的回调
    socket.on_close(() =>
    {
        console.log("close");
    })
});

app.websocket(websocket); // 将该实例通过websocket函数挂载在app上 , 这样当有ws协议的请求进入时,会自动处理

在浏览器,我们可以 :

const socket = new WebSocket("ws://localhost:9898");

    socket.onopen = function ()
    {
        console.log(1)
        socket.send("你好");
    }

    socket.onmessage = function (v)
    {
        console.log(v)
        socket.close();
    }

    socket.onclose = function ()
    {
        console.log('close')
    }

目前websocket有 message , error , connect ,close 四个事件可以绑定监听函数。

对于回调函数中的socket对象,实际上它是 Server_one_socket 类,但是在框架中并未暴露

Server_one_socket 类

它有四个属性和两个函数 :

socket; // 原始socket对象
error; // 当发生错误时的错误对象 默认null
payloadData; // 当获取到数据时的数据流对象
opcode; // 操作类型码

socket.write (buff); // write 函数 , 可以将数据写回前端 , 参数为 Buffer类型或 string类型
socket.close () // 结束本次socket连接

联系方式

无论是有bug或建议还是有技术缺陷可以 : [email protected] 或者直接好友联系 欢迎指正。