使用 Node 的简单 API 模拟工具






4.33/5 (2投票s)
一份在 Node 中创建 API 模拟工具的指南
引言
- 你的工作是否依赖于他人的 API?
- 由于 API 不可用,你的工作是否被延误?
- 你是否对开发 Node.js 工具感兴趣?
如果以上任何一个问题的答案是“是”,那么这篇文章就是为你准备的。
背景
API 的不断变化会破坏端点,还会消耗部署时间。这些 API 的变化会延迟前端团队的工作。因此,我考虑使用一些 API Mocking 工具,但所有这些工具都有自己的学习曲线。这促使我快速创建了一个简单明了的 API Mocking 工具。
关于该工具
该工具可帮助开发人员独立于 API 的可用性继续他们的任务。开发人员只需将所有 API 请求路由到该工具,它就会缓存响应,并在出错时返回 Mocked 响应。
用途
- 	安装 api-mock-proxynpm install -g api-mock-proxy 
- 	现在,你可以这样运行你的 Mock Proxy: api-mock-proxy -p 8000 -t http://your.api.com 现在你的代理服务器已在 https://:8000 准备就绪。只需在所有客户端中使用此 URL,你将从 http://your.api.com 获取响应。最棒的是,如果实际 API 不起作用,它将返回 Mocked 响应。 
可用选项
- 	port 或 -p: (默认:8080)- 指定 Mock 服务器将监听的端口
- 	targetUrl 或 -t: (默认:https://:80)- 指定 Mock 服务器将转发所有请求并返回响应的目标 URL。这将是你的实际 API 的 URL,Mock 服务器将保存响应以便在 API 响应错误时进行 Mock。
- 	errorCodes 或 -e: (默认:*)- 这将提供 Mocking 错误的选项,错误代码将以逗号分隔的列表提供,例如404,500,ECONNREFUSED默认值为*,这意味着它将为任何错误返回 Mocked 响应,除非处于录制模式。
- mode 或 -m: (默认:mix)- 它可以接受三个值中的任何一个- mock|- record|- mix- mock: Mock 所有请求,无需调用实际 API
- record: 始终从实际 API 返回响应并创建缓存以备将来 Mock
- mix: 调用实际 API 并返回实际响应,除了传递给- mockedError的错误代码。
 
- 	dataPath 或 -d: (默认:./data.json)- Mock 数据路径,它应该是有效的数据文件。第一次,只需指定路径,Mock 将在此位置创建。要运行 Mock 模式,必须预先填充 Mock 数据。
- 	--cors- 使用此选项为所有来源、方法和标头启用 CORS 标头
- 	allowOrigin- 提供一个string以用于响应标头 'Access-Control-Allow-Origin'
- 	allowMethods- 提供一个string以用于响应标头 'Access-Control-Allow-Methods'
- 	allowHeaders- 提供一个string以用于响应标头 'Access-Control-Allow-Headers'
- 	sslKey- 提供一个string作为 HTTPS 服务器的Key,只有同时提供了密钥和证书才会创建 HTTPS 服务器
- 	sslCert- 提供一个string作为 HTTPS 服务器的证书
- 	keyFile- 提供一个 Key 文件的路径,用于 HTTPS 服务器
- 	certFile- 提供一个 Certificate 文件的路径,用于 HTTPS 服务器
关于代码
代码按以下简单步骤编写:
- 读取用户输入或命令行参数
- 根据传递的参数创建 HTTP 服务器
- 请求目标服务器
- 返回实际或 Mocked 响应
现在我们将逐一理解。
处理命令行参数
有很多 NPM 包可用于处理命令行参数,例如 yargs、commander 等,但为了保持最少的依赖,该工具在没有任何第三方库的情况下处理命令行参数。Node.js 在一个数组中提供了所有命令行参数,可以轻松处理。例如,命令 api-mock-proxy -p 8000 -t http://your.api.com 将在你的程序中接收参数,如下所示:
[ 'C:\\Program Files\\nodejs\\node.exe',
  'C:\Users\admin\AppData\Roaming\npm\node_modules\api-mock-proxy',
  '-p',
  '8000',
  '-t',
  'http://your.api.com' ]
注意数组的前两个元素,它们是 node 和 package 的路径,所以参数应该从数组的第三个元素开始。
参数处理的另一个重要部分是提供默认值,因此为此使用了 lodash,这是一个用于所有此类任务的实用库。
const options = _.defaults(getOptions(myArgs), defaults);
创建代理服务器
处理完所有参数后,我们就准备好根据提供的选项创建代理服务器了。用户可以选择创建 HTTP 或 HTTPS 服务器,这可以通过使用原生的 Node.js 模块来完成:
const createServer = options.ssl ? _.curry(https.createServer)(sslOptions) : http.createServer;
const server = createServer((req, res) => { 
   // Request handling here 
}
sslOptions 包含 HTTPS 服务器的密钥和证书。
创建服务器后,一个重要部分是设置响应标头,如通过 CORS 相关标头或通过 --cors 标志在选项中提供的。
请求目标服务器
现在,下一步是将请求转发到目标服务器。如果用户没有选择仅通过使用 -m mock 或 --mode mock 来接收 Mocked 响应。服务器的每个响应将被存储为 Mocked 数据以供将来使用。响应将针对三个键进行保存,第一个是整个请求对象的哈希,第二个是去掉标头的请求的哈希,第三个是去掉标头和正文的请求的哈希。这样,我们就可以用最少的细节获取匹配的 Mocked 响应。
const fullHash = getHash(req);
const withOutHeader = getHash({ ...req, headers: "" });
const minHash = getHash({ ...req, headers: "", body: "" });
提供响应
对任何请求的实际响应将取决于用户的偏好。如果用户正在运行录制模式(-m record 或 --mode record)或混合模式下的无错误响应(-m mix 或 --mode mix 或不提供此选项),则在保存目标服务器响应后,将其转发。如果用户正在运行 Mock 模式(-m mock 或 --mode mock),或者目标服务器响应了 -e 404,500,ECONNREFUSED 或 --errorCodes * 指定的错误代码,则将返回 Mocked 响应。
要从 Mocked 数据中获取 Mocked 响应,第一步是找到在保存请求时创建的三个哈希请求键之一的响应。
for (let i = 0; i < reqHash.length; i++) {
  const item = reqHash[i];
  const existing = data[item];
  if (existing) {
    if (existing.length == 0) {
     return existing[0].res;
    } 
   return findBestMatch(existing, reqObj);
  }
}
如果哈希返回多个值,则它将使用 epsilonjs 找到最佳匹配,这是一个近似 string 匹配库,并且在整个数据中也使用相同的库,前提是哈希未找到匹配项。
const findBestMatch = (data, matchObj) => {
  const diffIndex = data.map(item => {
    return epsilon.leven(JSON.stringify(matchObj), JSON.stringify(item.req));
  });
  const minIndex = diffIndex.indexOf(Math.min(...diffIndex));
  const mock = data[Math.max(minIndex, 0)];
  return (mock || {}).res;
};
关注点
- 在 Node.js 中创建工具非常简单。
- 在你的主文件(package.json 的 main 键中指定的文件)的第一行添加 #!/usr/bin/env node,以使你的 Node.js 文件可执行。
- Node.js 将前两个参数作为 Node.js 可执行文件和正在执行的包/文件路径传递。
历史
下一步对于该工具很重要,那就是提供 UI 来创建 Mock 数据。

