http-svc
Version:
A HTTP request service for browser and node.js
1 lines • 52.9 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../src/shared.ts","../src/built-in/init-ctx.ts","../src/built-in/timeout.ts","../src/built-in/xsrf.ts","../src/built-in/body.ts","../src/built-in/fetch.ts","../src/built-in/res-data.ts","../src/built-in/spray.ts","../src/built-in/retry.ts","../src/built-in/cache.ts","../src/control/_.ts","../src/control/config.ts","../src/const/built-in-middleware.ts","../src/control/assemble.ts","../src/control/request.ts","../src/core.ts"],"sourcesContent":["import { BuiltInMiddleware, BuiltInMiddlewareName, IHttpSvcContext } from 'types/exports'\n\nexport const getBuiltInMiddlewareName = (name: BuiltInMiddleware): BuiltInMiddlewareName => `BUILT_IN_${name}`\n\nexport const createError = (ctx: IHttpSvcContext, message?: string): Error => {\n const error = new Error(message || `Request Error: ${ctx.response?.status || 'unknow status'}`) as any\n error.config = ctx.request\n if (ctx.response) {\n error.response = ctx.response\n if (!ctx.response.ok) {\n error.code = ctx.response.status\n }\n }\n return error\n}\n\nexport const isMiddleware = (middleware: any) => {\n if ((middleware as any).name && (middleware as any).handler) return true\n return false\n}\n\nexport const isNode: boolean = typeof window === 'undefined'\nexport const isArray = (val: any) => toString.call(val) === '[object Array]'\nexport const isObject = (val: any) => val !== null && typeof val === 'object'\nexport const isRecordObj = (obj) => Object.prototype.toString.call(obj) === '[object Object]'\nexport const isFormData = (val) => typeof FormData !== 'undefined' && val instanceof FormData\nexport const isFunc = (val: any) => val !== null && typeof val === 'function'\nexport const isDate = (val: any) => toString.call(val) === '[object Date]'\n\nexport const encodeParams = (val: string | number | boolean) => {\n return encodeURIComponent(val)\n .replace(/%3A/gi, ':')\n .replace(/%24/g, '$')\n .replace(/%2C/gi, ',')\n .replace(/%20/g, '+')\n .replace(/%5B/gi, '[')\n .replace(/%5D/gi, ']')\n}\n\nexport const buildURL = (url: string, params: { [x: string]: any }): string => {\n const parts: any = []\n\n Object.keys(params).forEach((key) => {\n let val = params[key]\n if (val === null || typeof val === 'undefined') {\n return\n }\n\n if (isArray(val)) {\n key = key + '[]'\n } else {\n val = [val]\n }\n val.forEach((v: string | number | boolean) => {\n if (isDate(v)) {\n v = v.toString()\n } else if (isObject(v as any)) {\n v = JSON.stringify(v)\n }\n parts.push(encodeParams(key) + '=' + encodeParams(v))\n })\n })\n\n const serializedParams = parts.join('&')\n\n if (serializedParams) {\n const hashMarkIndex = url.indexOf('#')\n if (hashMarkIndex !== -1) {\n url = url.slice(0, hashMarkIndex) as string\n }\n\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams\n }\n\n return url\n}\n\nexport const parseUrl = (url: string): { url: string; params?: Record<string, string> } => {\n const [u, s] = url.split('?')\n if (s) {\n const searchParams = s.split('&')\n if (searchParams.length) {\n const params = {}\n for (const searchParam of searchParams) {\n const [key, value] = searchParam.split('=')\n if (key && typeof value !== 'undefined') {\n params[key] = value\n }\n }\n return {\n url: u,\n params\n }\n }\n }\n return {\n url\n }\n}\n\nexport const formatString = (input) => {\n let afterFormat = ''\n for (let i = 0; i < input.length; i++) {\n afterFormat += String.fromCharCode(input.charCodeAt(i) - 1)\n }\n return afterFormat\n}\n\n// 标准的content-type key写法\nconst CONTENT_TYPE_KEY = 'Content-Type'\n\n// 从headers里取contenttype\nexport const getContentType = (headers?: Record<string, string>) => headers?.[CONTENT_TYPE_KEY] || headers?.['content-type'] // 非标准写法\nexport const setContentType = (headers: Record<string, string>, contentType: string) => {\n if (!contentType) return\n headers[CONTENT_TYPE_KEY] = contentType\n}\n\nexport const getCookie = (key: string, options?: { decode?: boolean; template?: string }) => {\n if (!options) options = {}\n const isNoDecode = options.decode === false\n const template = options.template || document.cookie\n const decodedCookie = isNoDecode ? template : decodeURIComponent(template)\n const cookies = decodedCookie.split(';')\n for (let i = 0; i < cookies.length; i++) {\n let cookie = cookies[i]\n while (cookie.charAt(0) === ' ') {\n cookie = cookie.substring(1)\n }\n const keyVal = cookie.split('=')\n const name = keyVal[0]\n const value = keyVal[1]\n if (key === name) return value\n }\n return ''\n}\n\nexport const setObjectValue = (obj: Record<string, any>, keyOrKeys: string | string[], value: any, spread?: boolean): void => {\n if (Array.isArray(keyOrKeys)) {\n const keys = [...keyOrKeys]\n while (keys.length) {\n if (keys.length === 1) {\n setObjectValue(obj, keys[0], value)\n break\n }\n const key = keys.shift() as string\n if (!isRecordObj(obj)) {\n if (typeof obj[key] === 'undefined' && spread) {\n obj[key] = {}\n } else {\n console.warn(`The value of \"${key}\" is not a record object!`)\n break\n }\n }\n obj = obj[key]\n }\n } else {\n const key = keyOrKeys\n obj[key] = value\n }\n}\n","import { IMiddlewareHandler, BuiltInMiddlewareName } from 'types/exports'\nimport { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { getBuiltInMiddlewareName, parseUrl } from '../shared'\n\nconst initCtx: IMiddlewareHandler = async function (ctx, next) {\n if (!ctx.request) return next()\n const { baseURL, headers, params, data, credentials = 'include' } = ctx.config\n let url = ctx.config.url\n\n const { url: originUrl, params: originParams } = parseUrl(url)\n // 初始化url 和params\n if (originParams) {\n url = ctx.request.url = originUrl\n ctx.request.params = {\n ...originParams,\n ...(params || {})\n }\n } else {\n ctx.request.url = url\n ctx.request.params = {\n ...(params || {})\n }\n }\n\n if (baseURL && /^(https?:)?\\/\\//.test(url) === false) {\n ctx.request.url = `${baseURL}${url}`\n }\n\n ctx.request.headers = {\n ...(headers || {})\n }\n if (data) {\n if (typeof data === 'object') {\n if (typeof FormData !== 'undefined' && data instanceof FormData) {\n const form = new FormData()\n const entries = Array.from((data as FormData).entries())\n entries.forEach(([key, value]) => {\n form.append(key, value)\n })\n ctx.request.data = form\n } else if (Object.keys(data)) {\n ctx.request.data = JSON.parse(JSON.stringify(data))\n }\n } else {\n ctx.request.data = data\n }\n }\n\n ctx.request.credentials = credentials\n return await next()\n}\n\nexport class HttpSvcInitCtx extends HttpSvcMiddleware {\n static handler = initCtx\n handler = initCtx\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('INIT_CTX')\n}\n","import { IMiddlewareHandler, BuiltInMiddlewareName } from 'types/exports'\nimport { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { getBuiltInMiddlewareName, isNode } from '../shared'\n\n// AbortController Polyfill for Node.JS based on EventEmitter for Node v14.6.x and below.\n\n// Are you using Node 14.7.0 or above? You don't need this! Node has AbortController and AbortSignal as builtin globals.\n// In Node versions >=14.7.0 and <15.4.0 you can access the experimental implementation using --experimental-abortcontroller.\nconst timeout: IMiddlewareHandler = async function (ctx, next) {\n let ms = ctx.config.timeout\n if (typeof ctx.config.timeout !== 'number') {\n ms = isNode ? 350 : 10000\n }\n if (!ctx.abortController && ms) {\n const abortController = new AbortController()\n ctx.abortController = abortController\n ctx.timeoutId = setTimeout(() => {\n abortController.abort()\n }, ms)\n await next()\n clearTimeout(ctx.timeoutId)\n } else {\n await next()\n }\n}\n\nexport class HttpSvcTimeout extends HttpSvcMiddleware {\n static handler = timeout\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('TIMEOUT')\n constructor() {\n super(timeout)\n }\n}\n","import { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { IMiddlewareHandler, BuiltInMiddlewareName } from 'types/exports'\nimport { IXsrfPayload } from 'types/middlewares/xsrf'\nimport { getBuiltInMiddlewareName, isNode, isRecordObj, isFormData, isObject, getCookie, setObjectValue } from '../shared'\n\nconst xsrf: IMiddlewareHandler<IXsrfPayload> = async function (ctx, next, config) {\n if (!ctx.request) return next()\n const payload: IXsrfPayload = config?.payload || { token: 'xsrf_token' }\n const { token, params, data, headers } = payload\n let xsrfValue: string | undefined\n if (params || data || headers) {\n try {\n if (!isNode) {\n xsrfValue = getCookie(token, { decode: false })\n } else {\n xsrfValue = getCookie(token, { template: ctx.request.headers?.['cookie'] || ctx.request.headers?.['Cookie'] || '_', decode: false })\n }\n } catch (error) {\n if (!isNode) {\n console.warn(error)\n }\n }\n }\n if (xsrfValue) {\n if (params) {\n setObjectValue(ctx.request, ['params', params], xsrfValue, true)\n }\n if (data) {\n if (typeof ctx.request.data === 'undefined') {\n setObjectValue(ctx.request, ['data', data], xsrfValue, true)\n } else if (isObject(ctx.request.data)) {\n if (isRecordObj(ctx.request.data)) {\n setObjectValue(ctx.request, ['data', data], xsrfValue, true)\n } else if (isFormData(ctx.request.data)) {\n ;(ctx.request.data as FormData).append(data, xsrfValue)\n }\n }\n }\n if (headers) {\n setObjectValue(ctx.request, ['headers', headers], xsrfValue, true)\n }\n }\n return await next()\n}\n\nexport class HttpSvcXsrf extends HttpSvcMiddleware<IXsrfPayload> {\n static handler = xsrf\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('XSRF')\n constructor(payload?: IXsrfPayload) {\n super({\n handler: xsrf,\n payload\n })\n }\n}\n","import { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { IMiddlewareHandler, BuiltInMiddlewareName, IHttpSvcContext } from 'types/exports'\nimport { IBodyPayload } from 'types/middlewares/body'\nimport { getBuiltInMiddlewareName, buildURL, getContentType, setContentType } from '../shared'\n\nexport enum ContentType {\n JSON = 'application/json',\n Form = 'application/x-www-form-urlencoded',\n FormData = 'multipart/form-data'\n}\n\nexport const isEqualContentType = (target: string, current?: string) => {\n if (!current) return false\n return current.indexOf(target) > -1\n}\n\nconst jsonBody = (ctx: IHttpSvcContext, data: Record<string, any>, contentType?: string) => {\n if (!ctx.request) return\n ctx.request.data = JSON.stringify(data)\n if (!ctx.request.headers) {\n const headers: Record<string, string> = {}\n setContentType(headers, ContentType.JSON)\n ctx.request.headers = headers\n } else if (!contentType) {\n setContentType(ctx.request.headers, ContentType.JSON)\n }\n}\n\nconst body: IMiddlewareHandler<IBodyPayload> = async function (ctx, next, config) {\n if (!ctx.request) return next()\n\n const { params, headers } = ctx.request\n\n // 处理query到url上\n ctx.request.url = buildURL(ctx.request.url, params || {})\n\n // 如果是post,需要将body处理好准备请求\n if (ctx.request.data) {\n // 这些对象不处理,只处理Record\n const isContinue = Object.prototype.toString.call(ctx.request.data) !== '[object Object]'\n if (!isContinue) {\n const contentType = getContentType(headers)\n const data = ctx.request.data as Record<string, any>\n if (config?.payload?.stringify) {\n jsonBody(ctx, data, contentType)\n return await next()\n }\n if (isEqualContentType(ContentType.Form, contentType)) {\n ctx.request.data = buildURL('', data).slice(1)\n }\n if (isEqualContentType(ContentType.JSON, contentType || ContentType.JSON)) {\n jsonBody(ctx, data, contentType)\n }\n if (isEqualContentType(ContentType.FormData, contentType)) {\n const keys = Object.keys(data)\n if (keys.length) {\n ctx.request.data = keys.reduce((form, key) => {\n form.append(key, data[key])\n return form\n }, new FormData())\n }\n }\n }\n }\n return await next()\n}\n\nexport class HttpSvcBody extends HttpSvcMiddleware<IBodyPayload> {\n static handler = body\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('BODY')\n constructor() {\n super(body)\n }\n}\n","import { IMiddlewareHandler, BuiltInMiddlewareName } from 'types/exports'\nimport { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { getBuiltInMiddlewareName, isNode } from '../shared'\n/**\n * 客户端fetch(window.fetch)\n * @param ctx\n * @param next\n * @returns\n */\nexport const fetch: IMiddlewareHandler = async (ctx, next) => {\n if (isNode) {\n throw new Error('When you are in a Node environment, please use server-side fetch middleware.')\n }\n if (!window.fetch) {\n throw new Error('When you are in a non-modern browser, please manually polyfill fetch.')\n }\n if (!ctx.request) return await next()\n if (ctx.response) return await next()\n const { url, method, headers, credentials } = ctx.request\n const body = ctx.request.data as BodyInit | undefined\n\n ctx.response = await window.fetch(url, {\n method,\n body,\n headers,\n credentials,\n signal: ctx.abortController?.signal\n })\n\n return await next()\n}\n\nexport class HttpSvcFetch extends HttpSvcMiddleware {\n static handler = fetch\n handler = fetch\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('FETCH')\n}\n","import { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { IMiddlewareHandler, BuiltInMiddlewareName } from 'types/exports'\nimport { IResDataPayload } from 'types/middlewares/res-data'\nimport { getBuiltInMiddlewareName } from '../shared'\n/**\n * 读response 的 data。\n * 一个可以绕过的中间件(在其前对response.data赋值即可绕过)\n * @param ctx\n * @param next\n * @returns\n */\nexport const resData: IMiddlewareHandler<IResDataPayload> = async function (ctx, next, config) {\n await next()\n if (ctx.response?.ok) {\n if (typeof ctx.response.data === 'undefined') {\n try {\n const responseType = config?.payload?.type || 'json'\n ctx.response.data = await ctx.response[responseType]()\n } catch (error) {\n console.warn(error)\n }\n }\n }\n}\n\nexport class HttpSvcResData extends HttpSvcMiddleware<IResDataPayload> {\n static handler = resData\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('RES_DATA')\n constructor() {\n super(resData)\n }\n}\n","/**\n * spray:(用作装饰的)小树枝,小花枝; (戴在身上的)一簇花\n */\nimport { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { IMiddlewareHandler, BuiltInMiddlewareName } from 'types/exports'\nimport { getBuiltInMiddlewareName } from '../shared'\n\nexport const spray: IMiddlewareHandler = async (ctx, next) => {\n await next()\n}\n\nexport class HttpSvcSprayMiddleware<T = any> extends HttpSvcMiddleware {\n static handler = spray\n name: BuiltInMiddlewareName = getBuiltInMiddlewareName('SPRAY')\n constructor(handler: IMiddlewareHandler, payload?: T) {\n super()\n // 不需要黑白名单逻辑\n this.handler = async (ctx, next) => {\n return await handler(ctx, next, { payload })\n }\n }\n}\n","import { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { IMiddlewareHandler } from 'types/exports'\nimport { IRetryPayload } from 'types/middlewares/retry'\nimport { createError, getBuiltInMiddlewareName } from '../shared'\n\n/**\n * 重试中间件\n * @param ctx\n * @param next\n * @returns\n */\n\n/**\n * 重试中间件\n * @param ctx\n * @param next\n * @returns\n */\n\nexport const retry: IMiddlewareHandler<IRetryPayload> = async (ctx, next, config) => {\n const requestFn = ctx.request?.function\n const { times, condition, onRetry } = config?.payload || { times: 0 }\n // 是否已经重试完毕(次数用尽)\n const isDone = () => {\n return !times || ctx.retry === times\n }\n // 进行重试的方法\n const doRetry = async (extra?: any) => {\n if (!requestFn) {\n throw createError(ctx, 'Missing request function')\n }\n if (isDone() && !config?.payload?.runtimeShortCircuit) {\n throw createError(ctx)\n }\n ctx.retry = ctx.retry ? ctx.retry + 1 : 1\n\n try {\n if (onRetry) {\n const newConfig = await onRetry(ctx.config, extra)\n if (newConfig) {\n ctx.config = newConfig\n }\n }\n if (ctx.response) delete ctx.response\n await requestFn(ctx)\n } catch (error: any) {\n throw createError(ctx, error.message)\n }\n }\n try {\n await next()\n } catch (error: any) {\n // 请求本身的错误\n if (isDone()) {\n throw createError(ctx, error?.message)\n }\n await doRetry()\n return\n }\n\n // 有条件函数,则调用函数,和上面不能放在一起\n if (condition) {\n // 如果命中条件\n const isMeetTheCondition = await condition(ctx.response!)\n // 命中就执行重试\n if (isMeetTheCondition) {\n await doRetry(isMeetTheCondition)\n return\n }\n }\n // 无响应或者响应不ok\n if (!ctx.response || !ctx.response.ok) {\n await doRetry()\n }\n}\n\nexport class HttpSvcRetry extends HttpSvcMiddleware<IRetryPayload> {\n static handler = retry\n name = getBuiltInMiddlewareName('RETRY')\n handler = retry\n}\n","import { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { IMiddlewareHandler } from 'types/exports'\nimport { ICachePayload, ICacheStore, IKeyDict } from 'types/middlewares/cache'\nimport { getBuiltInMiddlewareName } from '../shared'\n/**\n * 缓存中间件\n * @param ctx\n * @param next\n * @returns\n */\n\n// 通过dict 获取string key\nconst getKeyByKeyDict = (url: string, dict: IKeyDict): string => {\n return Object.keys(dict)\n .sort()\n .reduce((k, c) => {\n k += `_${c}:${dict[c]}`\n return k\n }, `api:${url}`)\n}\n\n// 缓存handler\nexport const cache: IMiddlewareHandler<ICachePayload> = async (ctx, next, config) => {\n // 兜底\n if (!ctx.request || ctx.request.method !== 'GET') return await next()\n // 如果没有载荷直接跳过\n if (!config?.payload) return await next()\n const { store, extra } = config.payload\n let key = config.payload.key\n // 如果没有缓存的key以及store,则缺少缓存能力的必要条件\n if (!key || !store) return await next()\n // 如果是字典,则将字典的值排序后得到一个字符串key\n if (typeof key !== 'string') key = getKeyByKeyDict(ctx.request.url, key)\n // 获取缓存数据,extra由调用方传入,自行与传入的store进行交互(如过期逻辑等)\n const data = store.get(key, extra)\n // 如果为非空数据,则直接使用这个数据生成response\n if (data) {\n ctx.response = new Response(JSON.stringify(data), {\n status: 200,\n statusText: `Cache:${key}`\n })\n await next()\n // 如果本轮读的是缓存,那就无需二次存储了\n } else {\n await next()\n // 如果本轮没有走缓存,那么可以执行设置缓存,设置逻辑由调用方自行控制\n if (ctx.response?.data) {\n store.set(key, ctx.response.data, extra)\n }\n }\n}\n\nexport class HttpSvcCache extends HttpSvcMiddleware<ICachePayload> {\n static handler = cache\n name = getBuiltInMiddlewareName('CACHE')\n constructor(store: ICacheStore) {\n super({\n handler: cache,\n payload: {\n store\n }\n })\n }\n}\n","import HttpService from '../core'\nexport abstract class HttpSvcControl {\n constructor(public httpSvc: HttpService) {}\n}\n","import { IMiddlewareContext, IMiddlewareHandlerConfig, IHttpSvcConfigControl, IMiddlewareContextProvider } from 'types/exports'\nimport { HttpSvcControl } from './_'\n\n/**\n * 中间件配置控制\n */\nexport class ConfigControl extends HttpSvcControl implements IHttpSvcConfigControl {\n /**\n * 提供\n * @param ctx 初始中间件上下文,可不传\n * @returns 中间件上下文提供者\n */\n public provide(ctx: IMiddlewareContext = {}): IMiddlewareContextProvider {\n const provider = {\n inject: (key: string, value: IMiddlewareHandlerConfig) => {\n this.inject(ctx, key, value)\n return provider\n },\n disable: (key: string) => {\n this.disable(ctx, key)\n return provider\n },\n get: () => {\n return ctx\n }\n }\n return provider\n }\n /**\n * 插入中间件的载荷\n * @param ctx 中间件上下文\n * @param name 中间件名称\n * @param config 中间件配置\n */\n private inject(ctx: IMiddlewareContext, name: string, config: IMiddlewareHandlerConfig) {\n ctx[name] = config\n }\n\n /**\n * 设置中间件禁用载荷\n * @param ctx 中间件上下文\n * @param name 需要禁用的中间件名称\n */\n private disable(ctx: IMiddlewareContext, name: string) {\n ctx[name] = {\n ...(ctx[name] || {}),\n disabled: true\n }\n }\n /**\n * 获取中间件在当前上下文的配置\n * @param ctx 中间件配置上下文\n * @param name 中间件名称\n * @returns 中间件的配置\n */\n public get(ctx: IMiddlewareContext, name: string) {\n return ctx[name] || {}\n }\n}\n","import { BuiltInMiddlewareName, BuiltInMiddleware } from 'types/exports'\nimport { getBuiltInMiddlewareName } from '../shared'\n\nexport const BUILT_IN_MIDDLEWARE: Record<BuiltInMiddleware, BuiltInMiddlewareName> = {\n INIT_CTX: getBuiltInMiddlewareName('INIT_CTX'),\n TIMEOUT: getBuiltInMiddlewareName('TIMEOUT'),\n BODY: getBuiltInMiddlewareName('BODY'),\n XSRF: getBuiltInMiddlewareName('XSRF'),\n FETCH: getBuiltInMiddlewareName('FETCH'),\n RETRY: getBuiltInMiddlewareName('RETRY'),\n SPRAY: getBuiltInMiddlewareName('SPRAY'),\n RES_DATA: getBuiltInMiddlewareName('RES_DATA'),\n RES_EXTRACT: getBuiltInMiddlewareName('RES_EXTRACT'),\n LOG: getBuiltInMiddlewareName('LOG'),\n CACHE: getBuiltInMiddlewareName('CACHE')\n}\n\nexport const ORDER_PRIFIX = '$ORDER_'\n","import {\n IFetchConfig,\n IHttpSvcMiddleware,\n IMiddlewareHandler,\n IHttpSvcContext,\n IAssembleDispatcher,\n IMiddlewareContextProvider,\n IHttpSvcAssembleControl,\n IRequestFunction,\n BuiltInMiddlewareName\n} from 'types/exports'\nimport { HttpSvcMiddleware } from '@http-svc/middleware'\nimport { HttpSvcControl } from './_'\nimport { HttpSvcInitCtx, HttpSvcTimeout, HttpSvcBody, HttpSvcResData, HttpSvcSprayMiddleware, HttpSvcRetry } from '../built-in'\nimport { createError, isMiddleware } from '../shared'\nimport { BUILT_IN_MIDDLEWARE, ORDER_PRIFIX } from '../const'\n\nclass AssembleDispatcher implements IAssembleDispatcher {\n public middlewares: IHttpSvcMiddleware[] = []\n public middlewareConfigCtxProvider: IMiddlewareContextProvider\n\n constructor(public control: AssembleControl) {\n this.middlewareConfigCtxProvider = this.control.httpSvc.configCtrl.provide()\n }\n\n public with(middleware: IHttpSvcMiddleware | IMiddlewareHandler | BuiltInMiddlewareName | string, payload?: any) {\n if (!middleware) return this\n if (typeof middleware === 'string') {\n this.middlewares.push({\n name: `${ORDER_PRIFIX}${middleware}`,\n handler: HttpSvcSprayMiddleware.handler\n })\n if (payload) {\n this.inject(middleware, payload)\n }\n } else if (typeof middleware === 'function') {\n this.middlewares.push(new HttpSvcSprayMiddleware(middleware as IMiddlewareHandler, payload) as HttpSvcMiddleware)\n } else if (isMiddleware(middleware)) {\n this.middlewares.push(middleware as IHttpSvcMiddleware)\n if (payload) {\n this.inject(middleware.name, payload)\n }\n }\n return this\n }\n\n /**\n * 插入中间件载荷\n * @param name 中间件名称\n * @param payload 中间件的载荷\n * @returns this\n */\n public inject(name: BuiltInMiddlewareName | string, payload: any) {\n // 包裹成config 再进行inject\n this.middlewareConfigCtxProvider.inject(name, { payload })\n return this\n }\n\n /**\n * 禁用中间件\n * @param name 中间件名称\n * @returns this\n */\n public disable(name: BuiltInMiddlewareName | string) {\n this.middlewareConfigCtxProvider.disable(name)\n return this\n }\n\n public request(config: IFetchConfig) {\n const fn = this.control.compose(this.middlewares)\n return this.control.httpSvc.requestCtrl.request(config, this.middlewareConfigCtxProvider.get(), fn)\n }\n}\n\n/**\n * 装配中间件控制\n */\nexport class AssembleControl extends HttpSvcControl implements IHttpSvcAssembleControl {\n // 中间件\n private middlewares: IHttpSvcMiddleware[] = []\n\n // 判断是否重复注册\n private alreadyExistsIdx(middlewareName: string) {\n return this.middlewares.findIndex((m) => m.name === middlewareName)\n }\n\n // 注册中间件\n public register(middlewares: IHttpSvcMiddleware[]): void {\n if (Array.isArray(middlewares)) {\n let reset = false\n middlewares.forEach((m) => {\n if (isMiddleware(m)) {\n reset = true\n const idx = this.alreadyExistsIdx(m.name)\n if (idx > -1) {\n this.middlewares[idx] = m\n } else {\n this.middlewares.push(m)\n }\n }\n })\n if (reset) {\n this.httpSvc.requestCtrl.reset()\n }\n }\n }\n\n // 启动装配调度\n private setup() {\n return new AssembleDispatcher(this)\n }\n\n /**\n * 禁用注册了的全局中间件\n * @param middlewareName 中间件名称\n * @returns dispatcher\n */\n public disable(middlewareName: BuiltInMiddlewareName | string) {\n return this.setup().disable(middlewareName)\n }\n\n /**\n * 挂载临时中间件\n * @param middleware 中间件\n * @param payload 中间件的载荷\n * @returns dispatcher\n */\n public with(middleware: IHttpSvcMiddleware | IMiddlewareHandler | BuiltInMiddlewareName | string, payload: any) {\n return this.setup().with(middleware, payload)\n }\n\n /**\n * 组织中间件,获得组织后的请求方法\n * @param middlewares 临时挂载的前中间件\n * @returns 请求方法\n */\n public compose(middlewares?: IHttpSvcMiddleware[]): IRequestFunction {\n // 全局中间件列表拷贝\n const list1: IHttpSvcMiddleware[] = [...this.middlewares]\n // 临时中间件收集\n const list2: IHttpSvcMiddleware[] = []\n\n const builtInOverride: Record<string, IHttpSvcMiddleware | null> = {\n [BUILT_IN_MIDDLEWARE.RETRY]: null,\n [BUILT_IN_MIDDLEWARE.BODY]: null,\n [BUILT_IN_MIDDLEWARE.RES_DATA]: null,\n [BUILT_IN_MIDDLEWARE.TIMEOUT]: null\n }\n\n const builtInNames = Object.keys(builtInOverride)\n const unique: Record<string, IHttpSvcMiddleware | null> = {}\n\n /**\n * 顺序逻辑:\n * 1. 如果是内置组件,走覆盖逻辑\n * 2. 非内置组件,同名中间件,with 覆盖 global;不同名中间件,global顺序靠洋葱外层,with顺序靠洋葱内层\n * 3. 如果是调整global 与 with 的调用顺序,可使用with(globalMiddlewareName, payload)\n */\n ;(middlewares || []).forEach((m) => {\n if (isMiddleware(m)) {\n let middlewareName = m.name\n if (builtInNames.includes(middlewareName)) {\n if (!builtInOverride[middlewareName]) {\n builtInOverride[middlewareName] = m\n }\n } else {\n // 如果是顺序调整\n if (middlewareName.startsWith(ORDER_PRIFIX)) {\n middlewareName = middlewareName.substring(ORDER_PRIFIX.length)\n // 必须是没设置过的\n if (!unique[middlewareName] && !(middlewareName in builtInOverride)) {\n const globalMiddlewareIndex = list1.findIndex((m) => m.name === middlewareName)\n if (globalMiddlewareIndex > -1) {\n // 取对应中间件\n const realM = list1[globalMiddlewareIndex]\n // 移除原列表\n list1.splice(globalMiddlewareIndex, 1)\n unique[middlewareName] = realM\n list2.push(realM)\n }\n }\n } else {\n // 临时函数中间件\n if (BUILT_IN_MIDDLEWARE.SPRAY === middlewareName) {\n list2.push(m)\n } else if (!unique[middlewareName]) {\n // 没用过的中间件\n unique[middlewareName] = m\n list2.push(m)\n }\n }\n }\n }\n })\n\n const list: IHttpSvcMiddleware[] = []\n\n list1.forEach((m) => {\n if (builtInNames.includes(m.name)) {\n if (!builtInOverride[m.name]) {\n builtInOverride[m.name] = m\n }\n } else if (!unique[m.name]) {\n list.push(m)\n }\n })\n\n list.push(...list2)\n\n const middlewareList = [\n // after 倒序\n // 重试\n builtInOverride[BUILT_IN_MIDDLEWARE.RETRY] || new HttpSvcRetry(),\n // before 正序\n new HttpSvcInitCtx(),\n // 临时 + 全局\n ...list,\n // 取res data\n builtInOverride[BUILT_IN_MIDDLEWARE.RES_DATA] || new HttpSvcResData(),\n // 处理body\n builtInOverride[BUILT_IN_MIDDLEWARE.BODY] || new HttpSvcBody(),\n // 开始超时计时\n builtInOverride[BUILT_IN_MIDDLEWARE.TIMEOUT] || new HttpSvcTimeout(),\n // fetch\n this.httpSvc.fetch as HttpSvcMiddleware\n // 有兜底处理\n ]\n return async (context: IHttpSvcContext) => {\n let index = -1\n const configCtrl = this.httpSvc.configCtrl\n const debug = configCtrl.get(context.middleware, 'DEBUG').payload\n await dispatch(0)\n if (debug) {\n return context\n }\n const disableResExtract = configCtrl.get(context.middleware, BUILT_IN_MIDDLEWARE.RES_EXTRACT).disabled\n if (!disableResExtract && context.response?.ok) {\n return context.response?.data || null\n }\n return context.response\n async function dispatch(i: number): Promise<any> {\n if (i === middlewareList.length) return\n if (i <= index) throw createError(context, 'The next() called multiple times')\n index = i\n const middleware = middlewareList[index]\n if (!middleware) {\n throw createError(context, 'Middleware is not exist')\n }\n await middleware.handler(context, dispatch.bind(null, i + 1), configCtrl.get(context.middleware, middleware.name))\n }\n }\n }\n}\n","import { HttpSvcControl } from './_'\nimport { IMiddlewareContext, IHttpSvcContext, IFetchConfig, IRequestFunction, FetchMethod, IUseAsyncRequest } from 'types/exports'\n/**\n * 请求控制\n */\nexport class RequestControl extends HttpSvcControl {\n // 基于全局中间件组织的默认请求方法\n private fn: IRequestFunction | null = null\n\n /**\n * 发起请求方法\n * @param config 请求配置\n * @param middlewareCtx 中间件配置上下文\n * @param fn 临时组织的请求方法\n * @returns\n */\n public async request(config: IFetchConfig, middlewareCtx: IMiddlewareContext = {}, fn?: IRequestFunction): Promise<any> {\n if (!fn) {\n if (!this.fn) {\n this.generateRequestFunction()\n }\n fn = this.fn as IRequestFunction\n }\n return await fn(this.createContext(config, middlewareCtx, fn))\n }\n\n private generateRequestFunction() {\n this.fn = this.httpSvc.assembleCtrl.compose()\n }\n\n public reset() {\n this.fn = null\n }\n\n private get useAsyncRequest(): IUseAsyncRequest {\n return (asyncRequest, config?) => {\n const inst = this.httpSvc.create(config)\n asyncRequest(inst.request.bind(inst))\n }\n }\n\n /**\n * 创建请求的上下文\n * @param config 请求配置\n * @param middleware 中间件上下文\n * @returns 请求上下文\n */\n private createContext(config: IFetchConfig, middleware: IMiddlewareContext = {}, requestFn): IHttpSvcContext {\n const { url, method } = config\n const ctx: IHttpSvcContext = {\n // 初始的config\n config: {\n baseURL: this.httpSvc.baseURL,\n ...config\n },\n useAsyncRequest: this.useAsyncRequest,\n middleware,\n request: {\n url,\n method: (method || 'get').toUpperCase() as FetchMethod,\n function: requestFn\n }\n }\n return ctx\n }\n}\n","import type {\n IHttpSvcMiddleware,\n IMiddlewareHandler,\n IHttpServiceInit,\n BuiltInMiddlewareName,\n IFetchConfig,\n IHttpService,\n FetchBaseURL,\n IAssembleDispatcher\n} from 'types/exports'\nimport { HttpSvcFetch } from './built-in'\nimport { ConfigControl } from './control/config'\nimport { AssembleControl } from './control/assemble'\nimport { RequestControl } from './control/request'\n\n/**\n * HTTP 服务\n * 一个基于中间件顺序组织调用的请求框架\n */\nexport default class HttpService implements IHttpService {\n // fetch 中间件,可由外部传入,但须按接口实现,不传入则使用内置fetch中间件\n public fetch: IHttpSvcMiddleware | undefined\n // 负责装配中间件的控制单元\n public assembleCtrl = new AssembleControl(this)\n // 负责管理每次请求的中间件配置上下文的控制单元\n public configCtrl = new ConfigControl(this)\n // 负责发起请求的控制单元\n public requestCtrl = new RequestControl(this)\n // 全局基本配置:baseURL,用于拼接请求仅传入path时,完善接口地址\n public baseURL: FetchBaseURL = '//api.domain.com'\n\n /**\n * 初始化\n * @param initConfig 初始配置,参考interface\n */\n constructor(initConfig?: IHttpServiceInit | IHttpSvcMiddleware[]) {\n if (initConfig) {\n // 如果是一个数组,认为是请求前(before)的中间件顺序数组\n if (Array.isArray(initConfig)) {\n // 使用默认中间件\n this.fetch = new HttpSvcFetch()\n this.register(initConfig)\n } else {\n // 如果是一个配置对象\n const { middlewares, fetch, baseURL } = initConfig\n // 可配fetch\n this.fetch = fetch || new HttpSvcFetch()\n this.register(middlewares || [])\n if (baseURL) this.baseURL = baseURL\n }\n } else {\n // 使用默认fetch\n this.fetch = new HttpSvcFetch()\n this.register([])\n }\n }\n\n // 注册中间件,调用装配控制\n public register(middlewares: IHttpSvcMiddleware[]): void {\n this.assembleCtrl.register(middlewares)\n }\n\n // 发起请求,调用请求控制\n public request<T = any>(config: IFetchConfig): Promise<T> {\n return this.requestCtrl.request(config)\n }\n\n // 禁用已注册的全局中间件\n public disable(middlewareName: BuiltInMiddlewareName | string): IAssembleDispatcher {\n return this.assembleCtrl.disable(middlewareName)\n }\n\n // 使用临时中间件,可附带载荷\n public with(middleware: IHttpSvcMiddleware | IMiddlewareHandler | BuiltInMiddlewareName | string, payload?: any): IAssembleDispatcher {\n return this.assembleCtrl.with(middleware, payload)\n }\n\n // 设置fetch中间件\n public setFetch(fetch: IHttpSvcMiddleware): void {\n this.fetch = fetch\n this.requestCtrl.reset()\n }\n\n // 创建一个实例\n public create(config?: IHttpServiceInit): IHttpService {\n return new HttpService({\n fetch: this.fetch,\n ...(config || {})\n })\n }\n}\n"],"names":["body","_a","m","fetch"],"mappings":"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