Code Monkey home page Code Monkey logo

Comments (4)

pengzhanbo avatar pengzhanbo commented on May 29, 2024

emmm.... 我理解你的想法。

在vite 中, server.proxy 是通过 http-proxy 实现的。但请求被 http-proxy 拦截并代理后,无论请求是否成功,请求都已经被消费。这表示,如果优先由 http-proxy 处理,即使 404 或 500 之类的错误码,请求也已经结束,不能继续被消费,也就是不会转到 mock 插件内进行处理。

而且假设可以实现, 被 http-proxy 代理的请求,等待响应的时间是不可控的,哪些状态码被认为是失败需要转到 本地mock 也是可能不止 404、4xx、5xx 等。这进一步引入了复杂度。

按照目前 vite 的实现,该功能是否能通过其他方式实现,我还需要进一步研究。

可替代的方法:

  1. 通过 enabled: false 禁用当前接口使用 本地mock数据,交给 vite 的 proxy 代理。
  2. 在 mock 文件中, 通过 fetch 或者 axios 进行请求,判断是否使用本地数据:
export default defineMock({
  url: '/api/url',
  body: async () => {
    try {
      const res = await fetch('http://example.com/api/url')
      return await res.json()
    } catch {
      return { message: 'local mock data' }
    }
  }
})

from vite-plugin-mock-dev-server.

gapkukb avatar gapkukb commented on May 29, 2024

的确是这样,目前我也卡在这个点上。

http-proxy的请求被消费完成后,在进入mock的时候,可以使用middleware拿到req,和res.如果是无body的请求,这可以很好的工作以实现预期.

但是,如果是携带body的请求,由于请求进入mock前已经被消费了(complete and destoryed)。无法使用on('data') on('end')等监听事件来提取body和response. 请求会被挂起无响应

关于这一点,你有什么主意吗,比如active这个已经消费掉的请求;或者重新产生请求,再使用ProxyRes.pipe()返回 (试过了但失败了)?

对于你最后的示例,只合适接口不多的时候,如果大量的接口使用这种重复劳动很显然是吃力的。

from vite-plugin-mock-dev-server.

pengzhanbo avatar pengzhanbo commented on May 29, 2024

在本插件中,提供了一种 请求复原 方式,将被 mock 消费后的 request 恢复并提交给 http-proxy

如果要实现 http-proxy -> mock request 的优先级顺序,在 vite 中, 可能就不能再使用 内置的 http-proxy 来处理,而是由插件全权进行 代理拦截,在插件内重新引入 http-proxy 以便完全的控制其行为;然后在此基础上实现 优先级的可配置。

但是我不确定这样做的带来的收益是否是正向的。

在我理解的 需要使用 mock request 的场景, 一般是:

  • 开发时, 接口数据的可靠性,获取在不同条件下的预期的数据;
  • 开发时,数据能够快速响应,减少接口等待,提高效率;
  • 联调时,即时切换到联调接口;
  • e2e 测试时,数据可靠性,可测试性;

这也是为什么 mock request 优先于 http-proxy 的原因; 但是两者的优先级翻转后,其行为反而导致了 开发时数据的不可预估,等待时间不可控等。

对于你最后的示例,只合适接口不多的时候,如果大量的接口使用这种重复劳动很显然是吃力的。

对于这个 大量接口的重复劳动问题,可以通过 createDefineMock 方法来批量处理:

比如,批量关闭某个 服务下的所有接口:

import { createDefineMock } from 'vite-plugin-mock-dev-server'

const defineMock = createDefineMock((mock) => {
  if (mock.url.startsWith('/api/services-a')) {
    mock.enabled = false
  }
})

export default defineMock({
  url: '/api/services-a'
})

通过预处理,借助 白名单 机制等,就可以批量控制 mock 的不同行为。

from vite-plugin-mock-dev-server.

pfdgithub avatar pfdgithub commented on May 29, 2024

你这个需求跟我之前的需求正好相反😂
我是优先使用本地 mock 文件,没有则使用 proxy 中转的后端接口。
你可以参考一下,把对本地 mock 文件的检查,替换为对远程接口的检查(比如用 axios.head 检查一下接口是否存在)
如果检查通过则调用 next() 调用后续的 proxy 中间件,如果检查不通过则使用本地 mock 文件返回。

// mock/_.mock.js

import fs from "fs";
import path from "path";
import colors from "picocolors";
import process from "process";
import { defineMock } from "vite-plugin-mock-dev-server";

const print = (type, msg) => {
  const date = colors.dim(new Date().toLocaleTimeString());
  const tag = colors.bold("[vite:mock-file]");

  if (type === "error") {
    console.error(`${date} ${colors.red(tag)} ${msg}`);
  } else if (type === "warn") {
    console.warn(`${date} ${colors.yellow(tag)} ${msg}`);
  } else {
    console.info(`${date} ${colors.cyan(tag)} ${msg}`);
  }
};

export default defineMock([
  {
    url: "/(.*)",
    response: async (req, res, next) => {
      if (!req.url) {
        return next();
      }

      const reqUrl = new URL(req.url, "http://localhost");
      const mockPath = path.join(process.cwd(), "mock", reqUrl.pathname);
      const mockFile = path.normalize(mockPath) + ".json";

      try {
        const mockContent = await fs.promises.readFile(mockFile, {
          encoding: "utf-8",
        });
        res.end(mockContent);
        print("info", `matched file: ${mockFile}`);
      } catch (err) {
        if (err.code === "ENOENT") {
          print("warn", `unmatch file: ${mockFile}`);
          // res.writeHead(404).end();
          next();
        } else {
          print("error", err);
          next(err);
        }
      }
    },
  },
]);

from vite-plugin-mock-dev-server.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.