支持离线的请求客户端,允许前端按照对应的接口规则创建模拟数据,然后离线进行前端流程测试
npm install koa-api-client
- 1.x for koa 1.x
npm install koa-api-client@~1
- 支持返回数据格式为
json
的请求
- 读取模拟数据;
- 记录请求的数据;
let baseUri = {
scheme: 'http',
domain: '127.0.0.1',
port: port,
prefix: '/api/v1'
};
let api = new ApiClient(baseUri, {
timeout: 15000, //网络请求超时时间
mock: process.env.NODE_ENV === 'production', //访问模拟数据
record: false, //记录请求返回的数据
beforeEnd: res => res //全局数据过滤器,对返回的数据做统一的处理
})
api.get('/banks', {type: 1}).then(...)
//this will request http://127.0.0.1/api/api/banks?type=1
//params will be cast to query params when request method is GET
let userApi = new ApiClient({domain: 'user.apiserver.com', prefix: '/v1'});
let activityApi = new ApiClient('http://activity.apiserver.com/v2');
userApi.post('/users/add', {name: 'userName', age: 18}.then(...)
activityApi.get('/activities', {startTime: '20170228'}.then(...)
具体用法可以参见/test/index.js中的后两个测试用例
let recordFolder = path.join(__dirname, '/mock');
let apiClient = new ApiClient(baseUri, {
mock: {
sleep: 1000, //模拟请求消耗时长
suffix: '.json', //数据文件后缀
dirLevel: MOCK_DIR_LEVEL, //相对请求路径的深度,默认为0
base: recordFolder //模拟数据的跟目录,配合dirLevel使用
}
});
apiClient.get('/banks', {
type: 1
}).then(res => {
//数据内容包含某个节点
expect(res.data['ABC']).to.have.property('name');
done();
}).catch(err => {
done(err);
})
具体用法可以参见/test/index.js中的后两个测试用例
let recordFolder = path.join(__dirname, '/mock');
let apiClient = new ApiClient(baseUri, {
record: {
suffix: '.json',
dirLevel: MOCK_DIR_LEVEL,
base: recordFolder
}
});
let recordFilePath = recordFolder + path.sep + 'api/v1/banks'.split('/').slice(MOCK_DIR_LEVEL).join(path.sep) + '.json';
if (fs.existsSync(recordFilePath)) {
fs.unlinkSync(recordFilePath);
}
apiClient.get('/banks', {
type: 1
}).then(res => {
fs.readFile(recordFilePath, 'utf8', function (err, data) {
assert.deepEqual(JSON.parse(data)
, res, 'file content is some with request content');
done(err);
});
}).catch(err => {
done(err);
})
var log4js = require('log4js'); //log4js@~1
log4js.configure({
appenders: [
{ type: 'console' },
{ type: 'file', filename: 'logs/api.log', category: 'koa-api-client' }
]
});
//set global logger for ApiClient
ApiClient.injectLogger(log4js.getLogger('koa-api-client'));
let api = new ApiClient('http://api.server.com/v1', {});
You can use any logger engine instance, it will detect the log node or log's info node(require type:function).
we use the debug
lib to console logs; set DEBUG=koa-api-client to console logs, more docs.
support each ApiClient and each request config
var xmlParser = require('xml2json');
var apiClient = new ApiClient(baseUri, Object.assign({
dataParser: (err, data) => err ? {
success: false,
msg: err.message
} : JSON.parse(xmlParser.toJson(data)).root
}, defaultOpt));
// server side will return '<root><data><ABC>bank</ABC></data><code>0</code></root>'
apiClient.get('/xml').then(res => {});;
//content is {data: {ABC: bank}, code: 0}
not support in each request's config
var apiClient = new ApiClient(baseUri, Object.assign({
beforeEnd: [
//if has valid data node, set success is true
data => {
data['success'] = !!data.data
return data;
},
//convert json node key to upper mode
data => {
Object.keys(data)
.forEach(key => {
data[key.toUpperCase()] = data[key];
delete data[key];
})
return data;
},
//log return data
data => {
console.log(JSON.stringify(data));
return data;
}
]
}, defaultOpt));
apiClient.get('/notfound').then(res => {});
1.server side use snake mode json data
router.get('/codeType/snake', function (cxt){
var snakeType = cxt.request.query['snake_type'];
if(snakeType){
cxt.body = {
success: true,
data: {
user_id: 'fadslkjfldaksjlf',
user_name: 'userName',
user_age: 27
}
};
}
})
client side also use snake mode, but now need to use camel mode, so can set requestMiddleware to convert request params and response data
var apiClient = new ApiClient(baseUri, Object.assign({
requestMiddleware: [
function (cxt, next) {
var request = cxt;
if (request.params) {
request.params = humps.decamelizeKeys(request.params);
}
return next()
.then(() => {
if (request.data) {
request.data = humps.camelizeKeys(request.data)
}
});
}
]
}, defaultOpt));
apiClient.get('/codeType/snake', {snakeType: 1}).then(res => {});
now, client use camel mode data without server side changes
- 需要考虑如何支持参数在链接上形式下,数据如何模拟读取和保存
- 通过mock数据约定格式,校验后台生产环境返回的数据,避免格式变更导致的前端报错
增加自定义的数据过滤函数池,统一对后台返回数据做处理。例如,蛇底转换成驼峰(config.beforeEnd/config.requestMiddleware)
- add advanced options requestMiddleware, you can set make some changes before and after request
- export injectLogger from ApiClient module directly, not from instance config
- add dataParser to custom convert data
- remove log4js module, accept log implement from option params.
use json5 to parse mock file, instead of json default
优化ApiClient的使用场景,允许无baseUri的实例化(utils.parseUriConfigToString
增加strictMode
参数)
修复url上存在参数后,自动补充参数错误的BUG