开发中为了快速交互数据库,于是需要一个能便捷搭建api的平台。于是学习了一下sails.js框架。本次实践是一次摸索,使用了winston日志记录,supertest单元测试,mongo数据库,hashids哈希值解密。
模块: winston+supertest+mongo+hashids
一、准备工作
我为了方便,使用docker拉取了一个mongodb的容器,在其中新建了my_widget_db数据库以及一个jobdetails集合。
jobdetails中数据样例属性如下:
jobId: 300***42
postingId: 1888***19
hash: JKMNlw*********5Pt7VQA
jonName: jobname1
安装日志模块以及加解密模块:
npm install winston
npm install hasids
模块需要配置一下 ,在config/bootstrap.js文件中:
const winston = require("winston");
const Hashids = require("hashids");
module.exports.bootstrap = async function() {const logConfiguration = {'transports': [new winston.transports.Console()]};sails.logger = winston.createLogger(logConfiguration);sails.hashids = new Hashids("JrY1ofkGxnByuIcFh0mHmIF6ieJLkwpM");
};
二、Sails.js用法
Sails.js是MVC架构的一个api搭建框架,创建一个项目:
sails new project-name
创建api命令,会生成一个controller文件和model文件(/api下的controller和model内):
sails generate api ApiName
在app/api/controller/ApiNameController.js中实现响应请求的代码。
比如请求获取jobdetails数据:
const responseError = (res, message, code = 400) => {res.status(code)res.send({message})return res
}const keys = ['jobId', 'postingId', 'hash', 'jobName']// 检查数据完整性
const checkData = (data) => {let status = truekeys.forEach(key => {if (!data[key]) {status = false}})return status
}// 检查非空参数数量
const checkParameters = (data) => {let c = 0;keys.forEach((key) => {if (data.param(key)) {// console.log(data.param(key))c++;}})return c;
}module.exports = {// 实现响应函数 getDetails,用于查询数据库中的数据async getJobDetails(req, res) {try {// check the number of paramslet counter = checkParameters(req)// console.log('params: ', `${counter}`)if (counter < 1) {return res.serverError('At least one parameter must be provided!');}let queryObject = {}keys.forEach(key =>{if (req.param(key)) {queryObject[key] = req.param(key)}})// JobDetails是我的model名称var getRecord = await JobDetails.find(queryObject).sort('createdAt DESC').limit(1);if (!getRecord && getRecord !== "undefined") {sails.logger.log('error', `jobId(${jobId}) not found`);return res.notFound();} else {getRecord.map(value =>{if (value.hash) {value.hash = sails.hashids.decode(value.hash);}if (value.createdAt) {delete value.createdAt;}if (value.updatedAt) {delete value.updatedAt;}if (value.id){delete value.id}return value})return res.json({data: getRecord});}} catch (err) {sails.logger.log('error', JSON.stringify(err));return res.serverError(err);}},
}
配置一下model/api.js文件
module.exports = {attributes: {jobId: {type: 'string'},postingId: {type: 'string'},hash: {type: 'string'},jobName: {type: 'string'},},};
接着设定网络请求的映射路由,将请求地址映射为此action响应函数 ,其中关于路由写法:
/jobdetails/:jobId?:postingId?:hash?:jobName?
表示/jobdetails/地址接收可选的参数有四个,分别是jobId,postingId,hash,jobName
module.exports.routes = {"GET /jobdetails/:jobId?:postingId?:hash?:jobName?": {controller: "JobDetailsController",action: "getJobDetails",cors: {origin: "http://127.0.0.1:3333, http://localhost:3333",credentials: false}// swagger: {},},
}
最后还需要配置一下数据库请求地址,我这里是docker容器,映射地址是
localhost:27018因此进行如下设置,一般mongodb默认的地址是localhost:27017,为了避免冲突我重映射为了27018端口。
在/config/datastores.js文件中添加:
module.exports.datastores = {mongodbServer: {adapter: 'sails-mongo',url: 'mongodb://localhost:27018/my_widget_db',},
};
三、接口测试
安装supertest模块,并在项目根目录下新建一个test文件夹:
npm install supertest
创建文件:/test/integration/controllers/ApiName.test.js
var supertest = require('supertest');
var sails = require('sails');
var assert = require('assert')describe('JobDetailsController', function () {[{'jobId':'300***42 '}].forEach( job =>{it(`getJobDetails ${job['jobID']}`, function (done) {let query = ''for(let k in job){query += '?' + kquery += '=' + job[k]}supertest(sails.hooks.http.app).get(`/jobdetails/${query}`).expect("Content-Type", /json/).expect(200).end(function (err, res) {if(res && res._body && res._body.data && res._body.data.length){return done()}else{return assert.ok(false,'There is no matching data in the database');}})})let data = []if(job['jobID']==='300***42 '){data = [{op:'add',path:'jobName',value:'jobnamehaschanged'}]}it(`patchJobDetails ${job['jobID']}`,function(done){supertest(sails.hooks.http.app).patch(`/jobdetails/${job['jobID']}`,data).expect("Content-Type", /json/).expect(200).end(function(err,res){if(res && res._body && res._body.length){return done()}else{return assert.ok(false,'There is no matching data in the database');//done(false)//done(new Error('There is no matching data in the database'))}})})})});
测试api:
npm run test
Postman 上测试: