diff --git a/docs/guide/middleware.md b/docs/guide/middleware.md index 9c5aaca..f5d26cb 100644 --- a/docs/guide/middleware.md +++ b/docs/guide/middleware.md @@ -53,8 +53,17 @@ async function (ctx, next) { | 已使用的属性名 | 含义和作用 | | --- | --- | | req | 请求 | -| req.reqFnParams | 发起请求所需的配置 | -| req.reqFnParams.reqParams | 请求的数据对象 | +| req.host | 服务器地址 | +| req.mock | 模拟的响应数据或是生成数据的函数 | +| req.type | 接口请求类型 get/post... | +| req.path | 接口结尾路径 | +| req.prefix | 接口前缀 | +| req.reqType | 使用什么工具发(axios/jsonp/wx) | +| req.reqParams | 已添加默认参数的请求参数 | +| req.callbackName | 使用 jsonp 时的回调函数名 | +| req.axiosOptions | 透传 axios 配置参数 | +| req.jsonpOptions | 透传 fetch-jsonp 配置参数| +| req.reqFnParams | 发起请求时的参数对象(上面那些参数都会被放进来作为属性) | | --- | --- | | res | 响应 | | res.data | 响应的数据 | diff --git a/examples/apis-web/fake-post.js b/examples/apis-web/fake-post.js index 3178b41..afe38ad 100644 --- a/examples/apis-web/fake-post.js +++ b/examples/apis-web/fake-post.js @@ -31,6 +31,21 @@ export default { reqType: 'axios', params: ['param1', 'param2'], }, + /** + * array-params with new host + */ + { + name: 'hap', + path: 'array-params', + type: 'post', + reqType: 'axios', + middleware: [ + async (ctx, next) => { + ctx.req.host = 'http://custom-host.com/' + await next() + }, + ], + }, /** * object-params */ diff --git a/package.json b/package.json index ccaeda0..705dc19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tua-api", - "version": "1.0.1", + "version": "1.1.0", "description": "🏗 A common tool helps converting configs to api functions", "main": "dist/TuaApi.cjs.js", "module": "dist/TuaApi.esm.js", diff --git a/src/TuaApi.js b/src/TuaApi.js index 4754784..f54422f 100644 --- a/src/TuaApi.js +++ b/src/TuaApi.js @@ -19,9 +19,9 @@ import { getFetchJsonpPromise, } from './adapters/' import { - setFullUrlMiddleware, formatResDataMiddleware, recordReqTimeMiddleware, + setReqFnParamsMiddleware, recordStartTimeMiddleware, formatReqParamsMiddleware, } from './middlewareFns' @@ -92,31 +92,37 @@ class TuaApi { /** * 根据 reqType 和 type 决定调用哪个库 * @param {Object} options + * @param {Object|Function} options.mock 模拟的响应数据或是生成数据的函数 * @param {String} options.url 接口地址 * @param {String} options.type 接口请求类型 get/post... * @param {String} options.fullUrl 完整接口地址 - * @param {String} options.path 接口路径名称 + * @param {String} options.reqType 使用什么工具发(axios/jsonp/wx) + * @param {Object} options.reqParams 请求参数 + * @param {String} options.callbackName 使用 jsonp 时的回调函数名 + * @param {Object} options.axiosOptions 透传 axios 配置参数 + * @param {Object} options.jsonpOptions 透传 fetch-jsonp 配置参数 * @return {Promise} */ _reqFn ({ url, + mock, type, fullUrl, reqType, reqParams: data, callbackName, - jsonpOptions, axiosOptions, + jsonpOptions, ...rest }) { // check type this._checkReqType(reqType) // mock data - if (rest.mock) { - const resData = typeof rest.mock === 'function' - ? rest.mock(data) - : { ...rest.mock } + if (mock) { + const resData = typeof mock === 'function' + ? mock(data) + : { ...mock } return Promise.resolve({ data: resData }) } @@ -175,7 +181,7 @@ class TuaApi { // 业务侧中间件函数数组 ...middlewareFns, // 生成 fullUrl 参数 - setFullUrlMiddleware, + setReqFnParamsMiddleware, // 统一转换响应数据为对象 formatResDataMiddleware, // 记录结束时间 @@ -199,7 +205,7 @@ class TuaApi { * @param {String} options.type 接口请求类型 get/post... * @param {Object|Function} options.mock 模拟的响应数据或是生成数据的函数 * @param {String} options.name 自定义的接口名称 - * @param {String} options.path 接口路径名称 + * @param {String} options.path 接口结尾路径 * @param {String[]} options.params 接口参数数组 * @param {String} options.prefix 接口前缀 * @param {Function} options.afterFn 在请求完成后执行的钩子函数(将被废弃) @@ -227,7 +233,6 @@ class TuaApi { }) { // 优先使用 name const apiName = name || path - const fullPath = `${prefix}/${path}` // 合并全局默认值 rest.host = rest.host || this.host @@ -253,7 +258,7 @@ class TuaApi { args = args === null ? {} : args // 最终的运行时配置,runtimeOptions 有最高优先级 - const runtimeParams = { type, path, params, prefix, apiName, fullPath, ...rest, ...runtimeOptions } + const runtimeParams = { type, path, params, prefix, apiName, ...rest, ...runtimeOptions } // 自定义回调函数名称(用于 jsonp) runtimeParams.callbackName = runtimeParams.callbackName || `${runtimeParams.path}Callback` @@ -292,7 +297,7 @@ class TuaApi { ) } - apiFn.key = fullPath + apiFn.key = `${prefix}/${path}` apiFn.mock = mock apiFn.params = params diff --git a/src/middlewareFns.js b/src/middlewareFns.js index de95dc5..057b0a9 100644 --- a/src/middlewareFns.js +++ b/src/middlewareFns.js @@ -56,11 +56,8 @@ const formatResDataMiddleware = (ctx, next) => next().then(() => { const formatReqParamsMiddleware = (ctx, next) => { const { args, - host, params, - fullPath, commonParams, - ...rest } = ctx.req if (typeof args !== 'object') { @@ -70,45 +67,43 @@ const formatReqParamsMiddleware = (ctx, next) => { checkArrayParams(ctx.req) // 根据配置生成请求的参数 - const reqParams = Array.isArray(params) + ctx.req.reqParams = Array.isArray(params) ? { ...commonParams, ...args } : { ...getDefaultParamObj(ctx.req), ...args } - // 请求地址 - const url = host + fullPath - - ctx.req.reqFnParams = { - ...ctx.req.reqFnParams, - ...rest, - url, - reqParams, - } - return next() } /** - * 设置请求 fullUrl 参数 + * 设置请求的 reqFnParams 参数,将被用于 _reqFn 函数 * @param {Object} ctx 上下文对象 * @param {Function} next 转移控制权给下一个中间件的函数 */ -const setFullUrlMiddleware = (ctx, next) => { - const { url, reqParams } = ctx.req.reqFnParams +const setReqFnParamsMiddleware = (ctx, next) => { + const { path, host, prefix, reqParams, ...rest } = ctx.req + // 请求地址 + const url = host + prefix + '/' + path const paramsStr = getParamStrFromObj(reqParams) - // 完整请求地址,将参数拼在 url 上,用于 get 请求 - ctx.req.reqFnParams.fullUrl = paramsStr - ? url + '?' + paramsStr - : url + const fullUrl = paramsStr ? `${url}?${paramsStr}` : url + + ctx.req.reqFnParams = { + url, + fullUrl, + reqParams, + ...rest, + // 若是用户自己传递 reqFnParams 则优先级最高 + ...ctx.req.reqFnParams, + } return next() } export { - setFullUrlMiddleware, recordReqTimeMiddleware, formatResDataMiddleware, + setReqFnParamsMiddleware, recordStartTimeMiddleware, formatReqParamsMiddleware, } diff --git a/test/__tests__/axios.test.js b/test/__tests__/axios.test.js index a80b84d..d906c41 100644 --- a/test/__tests__/axios.test.js +++ b/test/__tests__/axios.test.js @@ -18,6 +18,17 @@ const reqTAUrl = `http://example-base.com/fake-get/req-type-axios?asyncCp=asyncC const reqEAPUrl = `http://example-base.com/fake-post/empty-array-params` const reqMFDUrl = `http://example-base.com/fake-get/mock-function-data` +describe('middleware', () => { + test('change host before request', async () => { + const data = { code: 0, data: 'custom host' } + const reqHAPUrl = `http://custom-host.com/fake-post/array-params` + mock.onPost(reqHAPUrl).reply(200, data) + const resData = await fakePostApi.hap() + + expect(resData).toEqual(data) + }) +}) + describe('mock data', () => { test('mock function data', async () => { mock.onGet(reqMFDUrl).reply(200, {})