Commit f9da1759 authored by huhao's avatar huhao

😄

parents
.vscode/
node_modules/
\ No newline at end of file
module.exports = require('./yitong-sdk');
\ No newline at end of file
{
"name": "nodejs-yitong-sdk",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ansi-color": {
"version": "0.2.1",
"resolved": "https://registry.npm.taobao.org/ansi-color/download/ansi-color-0.2.1.tgz",
"integrity": "sha1-PnXAN0dSF1RO12Oo21cJ+prlv5o="
},
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npm.taobao.org/axios/download/axios-0.19.2.tgz",
"integrity": "sha1-PqNsXYgY0NX4qKl6bTa4bNwAyyc=",
"requires": {
"follow-redirects": "1.5.10"
}
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/buffer-equal-constant-time/download/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"bufrw": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/bufrw/download/bufrw-1.3.0.tgz",
"integrity": "sha1-KNbP2vNDADdoNjEPXDHVfutAyPo=",
"requires": {
"ansi-color": "^0.2.1",
"error": "^7.0.0",
"hexer": "^1.5.0",
"xtend": "^4.0.0"
}
},
"date-format": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/date-format/download/date-format-3.0.0.tgz",
"integrity": "sha1-64eANlx9KxURB4+0keZHl4DzrZU="
},
"debug": {
"version": "3.1.0",
"resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"requires": {
"ms": "2.0.0"
}
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npm.taobao.org/ecdsa-sig-formatter/download/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha1-rg8PothQRe8UqBfao86azQSJ5b8=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"error": {
"version": "7.0.2",
"resolved": "https://registry.npm.taobao.org/error/download/error-7.0.2.tgz?cache=0&sync_timestamp=1577615602648&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ferror%2Fdownload%2Ferror-7.0.2.tgz",
"integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=",
"requires": {
"string-template": "~0.2.1",
"xtend": "~4.0.0"
}
},
"flatted": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/flatted/download/flatted-2.0.1.tgz",
"integrity": "sha1-aeV8qo8OrLwoHS4stFjUb9tEngg="
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz",
"integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=",
"requires": {
"debug": "=3.1.0"
}
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz",
"integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=",
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"graceful-fs": {
"version": "4.2.3",
"resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.3.tgz",
"integrity": "sha1-ShL/G2A3bvCYYsIJPt2Qgyi+hCM="
},
"hexer": {
"version": "1.5.0",
"resolved": "https://registry.npm.taobao.org/hexer/download/hexer-1.5.0.tgz",
"integrity": "sha1-uGzoCFmOip0YksVx887dhvyfBlM=",
"requires": {
"ansi-color": "^0.2.1",
"minimist": "^1.1.0",
"process": "^0.10.0",
"xtend": "^4.0.0"
}
},
"jaeger-client": {
"version": "3.17.2",
"resolved": "https://registry.npm.taobao.org/jaeger-client/download/jaeger-client-3.17.2.tgz",
"integrity": "sha1-ks8mdSxcZvPmat9ZXN3i9UjMCAQ=",
"requires": {
"node-int64": "^0.4.0",
"opentracing": "^0.13.0",
"thriftrw": "^3.5.0",
"uuid": "^3.2.1",
"xorshift": "^0.2.0"
},
"dependencies": {
"opentracing": {
"version": "0.13.0",
"resolved": "https://registry.npm.taobao.org/opentracing/download/opentracing-0.13.0.tgz",
"integrity": "sha1-ajQUQvCdfYZrwR7QPeHjgo49aqs="
}
}
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "^4.1.6"
}
},
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npm.taobao.org/jsonwebtoken/download/jsonwebtoken-8.5.1.tgz",
"integrity": "sha1-AOceC431TCEhofJhN98igGc7zA0=",
"requires": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
}
}
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npm.taobao.org/jwa/download/jwa-1.4.1.tgz",
"integrity": "sha1-dDwymFy56YZVUw1TZBtmyGRbA5o=",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npm.taobao.org/jws/download/jws-3.2.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjws%2Fdownload%2Fjws-3.2.2.tgz",
"integrity": "sha1-ABCZ82OUaMlBQADpmZX6UvtHgwQ=",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&sync_timestamp=1563508077056&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz",
"integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npm.taobao.org/lodash.includes/download/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npm.taobao.org/lodash.isboolean/download/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npm.taobao.org/lodash.isinteger/download/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npm.taobao.org/lodash.isnumber/download/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "http://registry.npm.taobao.org/lodash.isplainobject/download/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npm.taobao.org/lodash.isstring/download/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/lodash.once/download/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"log4js": {
"version": "6.1.2",
"resolved": "https://registry.npm.taobao.org/log4js/download/log4js-6.1.2.tgz?cache=0&sync_timestamp=1581378918424&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flog4js%2Fdownload%2Flog4js-6.1.2.tgz",
"integrity": "sha1-BGiOH0uAgMEnt9zLDbHHWcuyXcQ=",
"requires": {
"date-format": "^3.0.0",
"debug": "^4.1.1",
"flatted": "^2.0.1",
"rfdc": "^1.1.4",
"streamroller": "^2.2.3"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "http://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz",
"integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
}
}
},
"long": {
"version": "2.4.0",
"resolved": "https://registry.npm.taobao.org/long/download/long-2.4.0.tgz",
"integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8="
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1584051509720&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
"integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npm.taobao.org/node-int64/download/node-int64-0.4.0.tgz",
"integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs="
},
"opentracing": {
"version": "0.14.4",
"resolved": "https://registry.npm.taobao.org/opentracing/download/opentracing-0.14.4.tgz",
"integrity": "sha1-oRNAjqdA2jqQ/eWzsAEaN1wuQmg="
},
"process": {
"version": "0.10.1",
"resolved": "http://registry.npm.taobao.org/process/download/process-0.10.1.tgz",
"integrity": "sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU="
},
"rfdc": {
"version": "1.1.4",
"resolved": "https://registry.npm.taobao.org/rfdc/download/rfdc-1.1.4.tgz",
"integrity": "sha1-unLME2egzNnPgahws7WL060H+MI="
},
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.0.tgz",
"integrity": "sha1-t02uxJsRSPiMZLaNSbHoFcHy9Rk="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz",
"integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc="
},
"streamroller": {
"version": "2.2.3",
"resolved": "https://registry.npm.taobao.org/streamroller/download/streamroller-2.2.3.tgz",
"integrity": "sha1-uVyfrUTi6JAF0kIUFIaztJYsLSg=",
"requires": {
"date-format": "^2.1.0",
"debug": "^4.1.1",
"fs-extra": "^8.1.0"
},
"dependencies": {
"date-format": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/date-format/download/date-format-2.1.0.tgz",
"integrity": "sha1-MdW16iEc9f12TNOLr50DPffhJc8="
},
"debug": {
"version": "4.1.1",
"resolved": "http://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz",
"integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
}
}
},
"string-template": {
"version": "0.2.1",
"resolved": "https://registry.npm.taobao.org/string-template/download/string-template-0.2.1.tgz",
"integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0="
},
"thriftrw": {
"version": "3.12.0",
"resolved": "https://registry.npm.taobao.org/thriftrw/download/thriftrw-3.12.0.tgz",
"integrity": "sha1-MIV4R3VefwNrLgp50RyfVQdVOdk=",
"requires": {
"bufrw": "^1.3.0",
"error": "7.0.2",
"long": "^2.4.0"
}
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&sync_timestamp=1583531006552&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz",
"integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY="
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1583326207173&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz",
"integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4="
},
"xorshift": {
"version": "0.2.1",
"resolved": "https://registry.npm.taobao.org/xorshift/download/xorshift-0.2.1.tgz",
"integrity": "sha1-/NgiZ+k1HBPw+5xzMH8lMx0pxjo="
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz",
"integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q="
}
}
}
{
"name": "nodejs-yitong-sdk",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.19.2",
"jaeger-client": "^3.17.2",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.15",
"log4js": "^6.1.2",
"opentracing": "^0.14.4"
}
}
/**
* 日志上报模块
*/
const _ = require('lodash');
const axios = require('axios');
const jsonwebtoken = require('jsonwebtoken');
const opentracing = require('opentracing');
const jaeger = require('jaeger-client');
const log = require('log4js').getLogger();
const httpLog = require('log4js').getLogger('http');
// 配置文件
const props = require('./props.json');
/**
* 业务异常
*/
class ApiError extends Error {
constructor(message, code) {
super(message)
this.code = code;
this.timestamp = Date.now();
}
toJSON() {
return {
timestamp: this.timestamp,
code: this.code,
message: this.message
}
}
}
/**
* YiTong SDK HTTP
*/
const http = axios.create({
method: 'POST',
headers: {
'content-type': 'application/json;charset=utf-8'
},
timeout: 60 * 1000, // 60秒超时
maxContentLength: 100 * 1024 * 1024,
httpAgent: new require('http').Agent({ keepAlive: true }),
httpsAgent: new require('https').Agent({ keepAlive: true })
});
// koa opentracing
// https://github.com/fapspirit/axios-opentracing
http.interceptors.request.use(function (config) {
if (config.context && config.context.span) {
let tracer = opentracing.globalTracer();
let span = tracer.startSpan(`${config.method}: ${config.url}`, {
childOf: config.context.span
});
config.span = span;
span.setTag(opentracing.Tags.COMPONENT, 'axios');
span.setTag(opentracing.Tags.SPAN_KIND, opentracing.Tags.SPAN_KIND_RPC_CLIENT);
span.setTag(opentracing.Tags.HTTP_METHOD, config.method);
span.setTag(opentracing.Tags.HTTP_URL, config.url);
tracer.inject(span, opentracing.FORMAT_HTTP_HEADERS, config.headers);
}
return config;
}, function (error) {
if (error.config && error.config.span) {
let { span } = error.config;
try {
span.setTag(opentracing.Tags.ERROR, true);
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, error.code);
span.log({ 'event': 'error', 'error.object': error.message });
span.finish();
} catch (e) {
log.error(e);
}
}
return Promise.reject(error);
});
http.interceptors.response.use(function (response) {
if (response.config && response.config.span) {
let { span } = response.config;
try {
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, response.status);
span.finish();
} catch (e) {
log.error(e);
}
}
return response;
}, function (error) {
if (error.config && error.config.span) {
let { span } = error.config;
try {
span.setTag(opentracing.Tags.ERROR, true);
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, error.code);
span.log({ 'event': 'error', 'error.object': error.message });
span.finish();
} catch (e) {
log.error(e);
}
}
return Promise.reject(error);
});
// YiTong JSON-RPC
http.interceptors.request.use(function (config) {
if (config.context && config.context.headers) {
// 有上下文环境,透传HTTP请求头
let { headers } = config.context;
Object.keys(headers).forEach(key => {
let key2 = key.toLowerCase();
if (config.headers[key2] === undefined) {
// 仅透传authorization及x-yt-自定义请求头
if (key2 === 'authorization' || key2.startsWith('x-yt-')) {
config.headers[key2] = headers[key];
}
}
});
}
return config;
});
http.interceptors.response.use(function (response) {
if (response.data) {
if (response.data.code === 1 || response.data.code === 0) {
return response.data.result;
}
}
return Promise.reject(response);
});
function sleep(ms) {
return new Promise((resolve, reject) => { setTimeout(resolve, ms) });
}
/**
* JSON RPC 返回值
*/
function ok(result, message) {
return {
timestamp: Date.now(),
code: 1,
message: message || '操作成功',
result: result
};
}
/**
* JSON RPC 异常
*/
function error(e) {
if (e) {
return new ApiError(e.message || '出错了', e.code || 9);
} else {
return new ApiError('出错了', 9);
}
}
/**
* JSON RPC 异常转换
*/
function transformError(e) {
// axios异常
if (e && e.request && e.status && e.data) {
e = e.data;
}
// 业务异常
if (e && e.timestamp && e.code && e.message) {
return e;
} else {
return error();
}
}
/**
* 异常处理中间件
*/
function errorHandler() {
return async function (ctx, next) {
try {
await next();
} catch (e) {
ctx.status = 200;
ctx.body = transformError(e);
log.error(e);
}
};
}
/**
* 调试中间件
*/
function debug() {
return async function (ctx, next) {
httpLog.debug(ctx.request.body);
await next();
// httpLog.debug(ctx.body);
};
}
/**
* opentracing链路跟踪中间件
* https://github.com/opentracing-contrib/javascript-express
*/
function tracing() {
opentracing.initGlobalTracer(jaeger.initTracer(props.tracing));
const tracer = opentracing.globalTracer();
return async function (ctx, next) {
let wireCtx = tracer.extract(opentracing.FORMAT_HTTP_HEADERS, ctx.headers);
let name = `${ctx.method}:${ctx.path}`;
let span = tracer.startSpan(name, { childOf: wireCtx });
ctx.span = span;
span.setTag(opentracing.Tags.COMPONENT, 'koa');
span.setTag(opentracing.Tags.SPAN_KIND, opentracing.Tags.SPAN_KIND_RPC_SERVER);
span.setTag(opentracing.Tags.HTTP_METHOD, ctx.method);
span.setTag(opentracing.Tags.HTTP_URL, ctx.url);
if (ctx.headers['user-agent']) {
span.setTag('http.headers.user_agent', ctx.headers['user-agent']);
}
if (ctx.headers['referer']) {
span.setTag('http.headers.referer', ctx.headers['referer']);
}
// 返回traceId,便于排查问题
let responseHeaders = {};
tracer.inject(span, opentracing.FORMAT_TEXT_MAP, responseHeaders);
Object.entries(responseHeaders).forEach(keyValue => {
let [key, value] = keyValue;
ctx.set(key, value);
});
try {
await next();
} catch (e) {
span.setTag(opentracing.Tags.ERROR, true);
span.setTag(opentracing.Tags.SAMPLING_PRIORITY, 1);
span.log({ 'event': 'error', 'error.object': e.message });
throw e;
} finally {
try {
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, ctx.status);
if (ctx.status >= 500) {
span.setTag(opentracing.Tags.ERROR, true);
span.setTag(opentracing.Tags.SAMPLING_PRIORITY, 1);
}
span.finish();
} catch (e) {
log.error(e);
}
}
};
}
/**
* YiTong 专用头部中间件
*/
function headerx() {
return async function (ctx, next) {
/**
* Authorization中token
*/
ctx.getAuthorizationToken = function () {
let authorization = /Bearer\s+(\S*)/i.exec(ctx.headers.authorization)
if (authorization && authorization[1]) {
return authorization[1];
}
// 兼容
return ctx.query.token || "";
};
/**
* 客户端Key
*/
ctx.getAppKey = function () {
return ctx.headers['x-yt-appkey'];
};
/**
* 客户端版本号
*/
ctx.getAppVersion = function () {
let appVersion = ctx.headers['x-yt-appversion'];
if (appVersion) {
return appVersion;
}
let userAgent = ctx.headers['user-agent'];
if (userAgent) {
let index = userAgent.lastIndexOf('/');
if (index > 0) {
return userAgent.substr(index + 1);
}
}
return undefined;
};
await next();
}
}
/**
* Token解析中间件
*/
function token() {
// token公钥,缓存
const publicKey = axios(`${props.apiBase}/auth/oauth2/public-key.pem`);
return async function (ctx, next) {
let authorizationToken = ctx.getAuthorizationToken();
if (authorizationToken) {
try {
let { data } = await publicKey;
// token解密,缓存
let token = jsonwebtoken.verify(authorizationToken, data);
ctx.token = token;
if (ctx.span) {
ctx.span.setTag('token.provider', token.iss);
ctx.span.setTag('token.app_key', token.aud);
ctx.span.setTag('token.subject', token.sub);
}
} catch (e) {
ctx.body = error({
code: 100,
message: '请重新登录'
});
if (ctx.span) {
ctx.span.setTag(opentracing.Tags.ERROR, true);
ctx.span.setTag(opentracing.Tags.SAMPLING_PRIORITY, 1);
ctx.span.log({ 'event': 'error', 'error.object': e.message });
}
return;
}
}
/**
* 当前请求token
*/
ctx.getToken = function () {
return ctx.token;
};
await next();
};
}
/**
* 鉴权中间件
*/
function auth() {
return async function (ctx, next) {
/**
* 当前用户
*/
ctx.getUser = function () {
if (ctx.token) {
return http({
context: ctx,
url: `${props.apiBase}/auth/v3/user/getUser`,
data: {
appKey: ctx.getAppKey()
}
});
} else {
return null;
}
};
/**
* 应用级token
*/
ctx.getApplicationToken = function () {
return http({
context: ctx,
url: `${props.apiBase}/auth/v3/application/getTokenByApplication`,
data: {
appKey: props.appKey,
appSecret: props.appSecret
}
});
};
await next();
};
}
/**
* 用户行为跟踪上报中间件
*/
function track() {
return async function (ctx, next) {
ctx.track = true; // 全部接口收集
ctx.trackEvent = {
__referer__: `${props.serviceName}:${ctx.path}`,
app_key: ctx.getAppKey() || _.get(ctx.token, 'aud') || props.appKey,
event: {
key: 'api'
},
segmentation: {},
session_id: ctx.ip,
user_details: {
user_id: _.get(ctx.token, 'sub')
}
}
let t = Date.now();
try {
await next();
} finally {
if (ctx.track && ctx.trackEvent.user_details.user_id) {
let { trackEvent } = ctx;
trackEvent.event.sum = Number(((Date.now() - t) / 1000.0).toFixed(3));
let trackQuery = Object.entries(trackEvent).map(keyValue => {
let [key, value] = keyValue;
if (Object.prototype.toString.call(value) === '[object String]') {
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
} else {
return `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(value))}`;
}
}).join('&');
axios({
method: 'GET',
url: `${props.trackBase}${trackQuery}`,
headers: {
'user-agent': ctx.headers['user-agent']
}
}).catch((e) => {
log.error(e);
});
}
}
};
}
/**
* 数据校验工具
*/
function validate(b, message) {
if (!b) {
throw error({
message: message || '参数错误',
code: 10
});
}
}
function equal(value, expected, message) {
if (value != expected) {
throw error({
message: message || '参数错误',
code: 10
});
}
}
function gt(value, expected, message) {
validate(value > expected, message);
}
function notEmpty(value, message) {
validate(!!value, message);
}
/**
* App扩展
*/
function extendApp(app) {
app.use(errorHandler()); // 启用异常处理
app.use(debug()); // 启用请求参数调试
app.use(tracing()); // 启用链路跟踪
app.use(headerx()); // 启用亿童请求头提取
app.use(token()); // 启动token解析
app.use(auth()); // 启动鉴权中间件
app.use(track()); // 启动用户行为跟踪
return app;
}
module.exports = {
http, // SDK客户端
sleep,
ok, // 正常请求返回封装
error, // 生成业务异常
transformError, // 处理各类异常,转为业务异常
errorHandler, // 异常处理中间件
debug, // 调试中间件
tracing, // 链路跟踪中间件
headerx, // 亿童请求头中间件
token, // token解析中间件
auth, // 鉴权中间件
track, // 用户行为跟踪中间件
validator: { // 数据校验工具
gt,
notEmpty,
equal
},
extendApp // koa扩展入口
};
// context扩展
// context.span // 链路跟踪rootSpan
// context.token // 当前请求token缓存,对象,已解析,请使用context.getToken()访问
// context.track // 是否跟踪用户行为开关(建议值)
// context.trackEvent // 用户行为跟踪事件
// context.getAuthorizationToken() // 获取Authorization请求头中token,字符串
// context.getAppKey() // 客户端Key
// context.getAppVersion() // 客户端版本号
// context.getToken() // 当前请求token,对象,已解析
// context.getUser() // 当前请求用户
// context.getApplicationToken() // 获取应用级token
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment