
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
yf-api-server
Advanced tools
一款灵活的api服务端,自动集成crud的数据操作,灵活扩展自定义业务逻辑
团队的产品从单平台,慢慢扩展到多个客户端,且有多个异构系统的数据交互,所以需要一个统一的数据输入输出口。
服务只有一个入口 /api ; 只接受post方式的请求,定义如下
| 参数名 | 类型 | 是否必须 | 参数说明 | 默认值 | 示例 |
|---|---|---|---|---|---|
| method | String | Y | 需要调用的业务函数 | 无 | |
| appkey | String | Y | 应用被分配的密钥 | 无 | |
| timestamp | Number | Y | 应用端的时间戳,用于验证请求的时效性 | 无 | 13位时间戳 |
| v | String | N | 调用的服务端接口的版本号 | 无 | |
| param | Object | N | 业务函数需要用到的参数,以JsonObject的形式传入 | 无 | |
| sign | String | Y | 将接口参数进行升序排列,如 appkey,method,param,timestamp添加一个masterKey=xxx[此处的key来自于注册的key] 组合成appkey=123&masterKey=xxx¶m=44444&tmiestamp=140932932932[所有的参数值使用urlencode] 过md5加密,生成一个32位的密钥 | 无 |
| 参数名 | 类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| errno | Number | Y | 业务函数的错误代码,通常为0,表示正常执行,<0 则表示执行错误,可通过应用说明获取到具体的错误原因。 |
| message | String | N | 通常在执行出错的情况下,会输出错误的信息。 |
| timestamp | Number | N | 返回服务端处理完信息之后的时间戳。 |
| data | Object/Array | Y | 一般的查询类的业务函数,会在该字段下携带查询结果信息;具体是Object类型还是Array类型则根据不同的业务函数的说明而定。 |
| error | Object | N | 错误信息的详细内容 |
这样的设计不能满足现在的restful范式,但是能满足我们团队现有的需求,提高了业务实现的开发效率;


依赖不少,请耐心等待几分钟。
$ npm install yf-api-server --save
需要手动创建一下logs记录日志文件的目录
$ mkdir logs
创建一个数据库和两张表
api_app:保存了appkey和secretkey的记录
api_record:记录每一次的接口请求

SQL脚本
--
-- 表的结构 `api_app`
--
CREATE TABLE IF NOT EXISTS `api_app` (
`id` int(12) NOT NULL AUTO_INCREMENT,
`appid` int(12) NOT NULL,
`appname` varchar(120) NOT NULL,
`apptype` varchar(120) NOT NULL,
`appkey` varchar(120) NOT NULL,
`secretkey` varchar(120) NOT NULL,
`appenvironment` varchar(120) NOT NULL,
`approot` varchar(120) NOT NULL,
`createAt` int(32) NOT NULL,
`updateAt` int(32) NOT NULL,
`delflag` int(12) NOT NULL,
`status` int(12) NOT NULL DEFAULT '1',
`about` varchar(250) NOT NULL,
`appurl` varchar(500) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `appid` (`appid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
-- 表的结构 `api_record`
--
CREATE TABLE IF NOT EXISTS `api_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`appkey` varchar(100) NOT NULL,
`createAt` bigint(20) NOT NULL,
`timestamp` bigint(20) NOT NULL,
`param` varchar(1000) NOT NULL,
`sign` varchar(100) NOT NULL,
`v` varchar(100) NOT NULL,
`method` varchar(100) NOT NULL,
`updateAt` bigint(20) NOT NULL,
`delflag` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
INSERT INTO `api_app` (`id`, `appid`, `appname`, `apptype`, `appkey`, `secretkey`, `appenvironment`, `approot`, `createAt`, `updateAt`, `delflag`, `status`, `about`, `appurl`) VALUES
(1, 10001, 'YFDemoKey', 'PC', 'a81bc1bb1122323b', '3fc4h39d3ed9b33b67fcbc359131e7ee', 'DEV', '*', 1462610156, 1462773916, 0, 1, 'YF所有,抄袭必究', NULL)
-- 这里的appkey 和 secretkey会在接口调用的时候被使用到
-- appkey : 'a81bc1bb1122323b'
$ touch config.js
$ vi config.js
var k = {
db:{
host: '192.168.1.1',
port:3306,
username:'root',
password:'',
},
database:{'api':'api'},
server:{port:8080},
dev:'DEV'
};
var getDbConfig = function(option){
var originConfig = {
host: 'localhost',
port:3306,
username:'root',
password:'',
debug:false,
pool:{
connectionLimit:10,
queueLimit:0,
waitForConnections:true
}
};
for(var key in k.db){
originConfig[key] = k.db[key];
}
for(var key in option){
originConfig[key] = option[key];
}
return originConfig;
};
module.exports = {
db:(function(database){
var _dbs = {};
for(var d in database){
_dbs[d] = getDbConfig({database:database[d]});
}
return _dbs;
})(k.database),
server: k.server||{
port: k.dev == 'PRODUCT'?9001:8080
},
defaultVersion:'0.0.1',
dev:k.dev,
log4js: {
appenders: [
{ type: 'console' },{
type: 'file',
filename: 'logs/access.log',
maxLogSize: 1024 * 1024 * 100, //100Mb一个文件
backups:10,
category: 'normal'
}
],
replaceConsole: true,
levels:{
dateFileLog: 'debug',
console: 'errno'
}
}
};
编写代码,最终的目录结构预览如下

$ mkdir V0.0.2 && cd V0.0.2 && touch index.js && vi index.js
'use strict';
var _ = require('underscore');
var Q = require('q');
module.exports = function(C,M,H){
var q = Q.defer();
M.test = function(){
var _q = Q.defer();
_q.resolve({data:"中文和zimu from v0.0.2"})
return _q.promise;
}
q.resolve({'foo':M}); //业务名称: foo.test
return q.promise;
};
$ touch app.js
$ vi app.js
var async = require('async');
var config = require('./config.js');
var M = {};
var v002 = require('./V0.0.2');
var yfserver = require('yf-api-server');
var app = yfserver(config);
async.parallel({
'0.0.2':function(cb){
v002(config,M,yfserver.hook).then(function(biz){
cb(null,biz);
});
}
},function(err,results){
if(err){
console.log(err);
return;
}
app.setBizModules(results);
app.start();
}
);
$ node app.js

postman测试

到此,一个能满足基本业务的api服务端就搭建好了 目前我的项目在使用它做生产环境了

pm2 logs

欢迎拍砖~~
我部署了一个demo项目,代码在这里 https://github.com/yfsoftcom/yf-demo-api
请笑纳~

FAQs
> 一款灵活的api服务端,自动集成crud的数据操作,灵活扩展自定义业务逻辑
The npm package yf-api-server receives a total of 28 weekly downloads. As such, yf-api-server popularity was classified as not popular.
We found that yf-api-server demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.