ming_node
介绍
ming_node是什么
ming_node是用于快速构建web服务与接口测试的工具库,使用方法与express非常类似,并且ming_node只有一个文件,ming_node可以随用随扔而又让人不感到可惜,ming_node的web服务部分是参照express来写的.
安装
更新日志
最新稳定版本:v1.8.2
项目主页 GitHub
每个版本的更新日志 GitHub
项目地址 GitHub
npm地址 NPM
NPM
ming_node无任何第三方依赖,只是一个比较大的js文件.
# 最新稳定版
npm i ming_node
0依赖引入
https://minglie.github.io/js/ming_node.js
+async function () {
M = await new Promise((v) => require('https').get("https://minglie.github.io/js/ming_node.js", (q) => { d = ''; q.on('data', (a) => d += a); q.on('end', () => v(eval(d))) }))
var app = M.server();
app.listen(8888);
app.get("/getById", async (req, res) => {
console.log(req.params);
res.send("ok");
})
}();
起步
官方指南假设你已了解关于node, commonJs, npm的初级知识。如果你没用过node不知道npm,
花点时间了解一下http://www.runoob.com/nodejs/nodejs-install-setup.html, 把node环境装上就ok了.
快速体验
下面是ming_node关于web服务的最小环境 ,如果你只对web服务感兴趣可以直接看 Web服务章节
var M = require("ming_node");
var app = M.server();
app.listen(8888);//服务在8888端口监听
app.get("/getById", (req, res) => {
console.log(req.params);//任何形式的请求参数全部已经封装在req.params里
res.send("ok");//响应一个"ok"字符串
})
在浏览器中输入http://localhost:8888/getById?id=5 效果如下图
token,csrf等的处理
我没有封装相关方法,但是用原生方法结合全局作用域能很容易实现,只是读请求头,设置响应头的东西,
下面是一个token 鉴权的例子
M=require("ming_node")
app=M.server()
app.listen(8888)
token="abcdefg"
app.get("/getUserById",(req,res)=>{
console.log(req.params)
if(req.headers["authorization"]==token){
id=req.params.id;
res.send(M.result("ok"));
}else{
res.send(M.result("无权访问"));
}
})
SSE服务端推送消息到浏览器
服务端代码
var M=require("ming_node");
var app=M.server();
app.listen(8888);
sseApp=M.sseServer()
sseApp.listen(2000)
app.get("/getById",(req,res)=>{
console.log(req.params);
sseApp.send(JSON.stringify(req.params));
res.send("ok");
})
或者共有Web服务端口
var M=require("ming_node");
var app=M.server();
app.listen(8888);
sseApp=M.sseServer()
//sseApp.listen(2000)
app.get("/sseServer",sseApp)
app.get("/getById",(req,res)=>{
console.log(req.params);
sseApp.send(JSON.stringify(req.params));
res.send("ok");
})
浏览器代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>xxx</title>
</head>
<body>
<h1>获取服务端更新数据</h1>
<div id="result"></div>
<script>
if (window.EventSource) {
// 创建 EventSource 对象连接服务器
const source = new EventSource('http://localhost:2000');
// 连接成功后会触发 open 事件
source.addEventListener('open', () => {
console.log('Connected');
}, false);
// 服务器发送信息到客户端时,如果没有 event 字段,默认会触发 message 事件
source.addEventListener('message', e => {
console.log(`data: ${e.data}`);
}, false);
// 自定义 EventHandler,在收到 event 字段为 slide 的消息时触发
source.addEventListener('slide', e => {
result.innerText+=e.data;
console.log(`data: ${e.data}`);
}, false);
// 连接异常时会触发 error 事件并自动重连
source.addEventListener('error', e => {
if (e.target.readyState === EventSource.CLOSED) {
console.log('Disconnected');
} else if (e.target.readyState === EventSource.CONNECTING) {
console.log('Connecting...');
}
}, false);
} else {
console.error('Your browser doesn\'t support SSE');
}
</script>
</body>
</html>
或者使用ming_mock
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>xxx</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script src="https://minglie.github.io/js/M_mock.js"></script>
</head>
<body>
<h1>获取服务端更新数据</h1>
<div id="result"></div>
<script>
M.EventSource('http://localhost:2000',function(e){
result.innerText+=e.data;
})
</script>
</body>
</html>
效果

前端学习环境搭建
为了方便前端学习可以使用 ming_node与ming_click搭建一个方便的环境
后端代码
var M=require("ming_node");
var app=M.server();
app.listen(8888);
app.get("/",async (req,res)=>{
app.redirect("/index.html",req,res)
})
app.get("/pagelist",async (req,res)=>{
//如果是linux系统应改用 M.exec("ls static")
let s= await M.exec("dir static /b")
res.send(M.result(s))
})
或者0依赖
+async function () {
M = await new Promise((v) => require('https').get("https://minglie.github.io/js/ming_node.js", (q) => { d = ''; q.on('data', (a) => d += a); q.on('end', () => v(eval(d))) }))
var app = M.server();
app.listen(8888);
app.get("/", async (req, res) => {
app.redirect("/index.html", req, res)
})
app.get("/pagelist",async (req,res)=>{
//如果是linux系统应改用 M.exec("ls static")
let s= await M.exec("dir static /b")
res.send(M.result(s))
})
}();
前端代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<h1>网页列表</h1>
<div v-for="file in list">
<a :href="file">{{ file }}</a>
</div>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data() {
return {
list: null
}
},
mounted() {
M_this = this;
fetch('/pagelist').then(function (response) {
return response.json();
}).then(function (response) {
let list = response.data.split("\n");
list = list.filter((d) => (d.indexOf(".html") >= 0))
console.log(list)
M_this.list = list
});
}
})
</script>
</body>
</html>
前后端代码还可以合并
+async function () {
M = await new Promise((v) => require('https').get("https://minglie.github.io/js/ming_node.js", (q) => { d = ''; q.on('data', (a) => d += a); q.on('end', () => v(eval(d))) }))
url = require("url");
var app = M.server();
app.set("views", "./")
app.listen(8888);
app.begin((req, res) => {
if (req.url.includes(".html")) {
let obj = url.parse("?" + req.url, true);
req.url = "/" + Object.keys(obj.query)[0].slice(1)
}
console.log(req.url)
})
app.get("/pagelist", async (req, res) => {
//如果是linux系统应改用 M.exec("ls static")
let s = await M.exec("ls")
res.send(M.result(s))
})
app.get("/", async (req, res) => {
res.writeHead(200, { "Content-Type": "text/html;charset='utf-8'" });
res.write(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<h1>网页列表</h1>
<div v-for="file in list">
<a :href="file">{{ file }}</a>
</div>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data() {
return {
list: null
}
},
mounted() {
M_this = this;
fetch('/pagelist').then(function (response) {
return response.json();
}).then(function (response) {
let list = response.data.split("\\n");
list = list.filter((d) => (d.indexOf(".html") >= 0))
console.log(list)
M_this.list = list
});
}
})
</script>
</body>
</html>`
);
res.end(); /*结束响应*/
})
}();
ming_click自动刷新浏览器
如果需要自动刷新浏览器,可以在后端加入这两行代码,原理是用C语言找到页面的窗口句柄,模拟按下F5键
https://github.com/minglie/ming_click
var C = require('ming_click');
C.watch("./static")
其他方法
//执行一条系统命令,打印当前的TCP/IP配置的设置值
console.log(M.exec("ipconfig"))
//延时指定毫秒
M.sleep(numberMillis)
//下划线转驼峰,打印"userId"
console.log("user_id".underlineToHump())
//驼峰转下划线,打印"user_id"
console.log("userId".humpToUnderline())
//首字母变大写,打印"User"
console.log("user".firstChartoUpper())
//首字母变小写,打印"uSER"
console.log("USER".firstChartoLower())
//打印当前日期,2019-03-24
console.log(new Date().format("yyyy-MM-dd"))
其他ming_node相关
便捷的静态web服务
在含有static文件夹的目录执行下面命令,static便作为web根目录
#node
curl https://minglie.github.io/js/index.js > index.js && node index.js
#python
curl https://minglie.github.io/python/index.py > index.py && python index.py
#启动ming_mock_server
git clone https://github.com/minglie/ming_mockServer.git && cd ming_mockServer && npm i && npm run start
#curl启动ming_mockServer0
curl https://minglie.gitee.io/mingpage/static/js/ming_mockServer0.js > index.js && node index.js
当前目录静态页
curl https://minglie.gitee.io/mingpage/static/js/index_cur.js > index.js && node index.js
+async function(){
M =await new Promise((v)=>require('https').get("https://minglie.github.io/js/ming_node.js",(q)=>{d='';q.on('data',(a)=>d+=a);q.on('end',()=>v(eval(d)))}))
var app=M.server();
app.set("views","./")
app.listen(8888);
app.get("/",async (req,res)=>{
app.redirect("/index.html",req,res)
})
}();
接口代理
/**
POST http://localhost:8888/axios
{
"url": "https://www.baidu.com/",
"method":"get",
"headers": {"Content-Type": "application/json"},
"params": {
"dd":848
},
"data": {
"id":5
}
}
*/
function myAxios(body) {
let bodyObj = JSON.parse(body);
return new Promise((r, j) => {
try {
let getData = {}
if (bodyObj.method == "post") {
if (bodyObj.params) {
let getData = Object.keys(bodyObj.params).map(u => u + "=" + bodyObj.params[u]).join("&");
if (bodyObj.url.indexOf("?") > 0) {
getData = "&" + getData;
} else {
getData = "?" + getData;
}
bodyObj.url = bodyObj.url + getData;
}
M.post(bodyObj.url, r, bodyObj.data, bodyObj.headers)
} else {
M.get(bodyObj.url, r, bodyObj.params, bodyObj.headers)
}
} catch (e) {
j(e);
}
});
}
app.post("/axios", async (req, res) => {
console.log(req.body)
let r = await myAxios(req.body)
res.send(M.result(r));
})
写web接口最快捷的方式ming_share_edit
运行脚本, 访问 http://localhost:8888/
curl https://minglie.gitee.io/mi/i2.js > index.js && node index.js

ming_api_mock
因为 ming_share_edit采用txt格式存储文件,不便于编辑器查看,以及启动文件的冗余,不支持多服务文件,因此有了命令行工具 [ming_api_mock](https://www.yuque.com/docs/share/fc8547e1-e815-4e50-817c-4829e3c76442?#)
网友评论