whistle-plugins / whistle.script

Custom extension script for whistle
MIT License
65 stars 12 forks source link

URL一样的的Post请求,想根据reqBody里的不同参数,返回不同的resBody #39

Open shownstrong opened 4 months ago

shownstrong commented 4 months ago

1.目前普通用法配置规则resBody://{reponse1}, 由于post请求的url都是一致的,每次mock不同数据需要临时重新修改。 不知道是否能定义规则,根据不同的reqBody,返回不同的resBody。一次性配置好,不需要临时再修改

2.尝试过whistle.script://test

 exports.handleRequestRules = (ctx) => {
    // ctx.fullUrl 可以获取请求url
    // ctx.headers 可以获取请求头
    // ctx.options 里面包含一些特殊的请求头字段,分别可以获取一些额外信息,如请求方法、设置的规则等
    ctx.rules = ['www.qq.com file://{test.html}'];
    ctx.values = { 'test.html': 'Hello world.' };
 };

测试过Readme文档里的test脚本,可以mock成功。但是尝试获取请求体失败。

 // 获取请求体数据
  const requestBody = await new Promise((resolve, reject) => {
    let data = [];
    ctx.req.on('data', chunk => {
      data.push(chunk);
    });
    ctx.req.on('end', () => {
      resolve(Buffer.concat(data));
    });
    ctx.req.on('error', err => {
      reject(err);
    });
  });

  // 转换请求体数据为字符串
  const requestBodyString = requestBody.toString();
  console.log('原始请求体数据长度:', requestBody.length);
  console.log('原始请求体数据:', requestBodyString);

  // 解析 JSON 格式的请求体数据
  let bodyData;
  if (requestBodyString) {
    try {
      bodyData = JSON.parse(requestBodyString);
    } catch (err) {
      console.error('请求体解析错误:', err);
      console.error('解析失败的请求体:', requestBodyString);
      bodyData = null;
    }
  } else {
    console.log('请求体为空');
    bodyData = null;
  }

js小白,麻烦大佬有空指导下

shownstrong commented 4 months ago

Version: 2.9.74

avwo commented 4 months ago

可以通过过滤器 excludeFilter://b:patternincludeFilter://b:pattern 匹配请求内容,看下能不能满足需求:https://wproxy.org/whistle/rules/filter.html

shownstrong commented 4 months ago

可以通过过滤器 excludeFilter://b:patternincludeFilter://b:pattern 匹配请求内容,看下能不能满足需求:https://wproxy.org/whistle/rules/filter.html

1.感谢大佬,测试通过。不过我理解这种只适合用于reqBody取1个参数来判断的情况,如果要取多个参数,就不合适了。

2.对于whistle.script://test的方式,有解析reqBody的范例或者文档吗

avwo commented 4 months ago

可用正则表达式,过滤器也可以同时设置多个

sosohime commented 4 months ago

可以通过过滤器 excludeFilter://b:patternincludeFilter://b:pattern 匹配请求内容,看下能不能满足需求:https://wproxy.org/whistle/rules/filter.html

1.感谢大佬,测试通过。不过我理解这种只适合用于reqBody取1个参数来判断的情况,如果要取多个参数,就不合适了。

2.对于whistle.script://test的方式,有解析reqBody的范例或者文档吗

注意插件规则配置是script://test,不是whistle.script://test

参考

exports.handleRequest = (ctx, request) => {
    // ctx.fullUrl 可以获取请求url
    // ctx.headers 可以获取请求头
    // ctx.options 里面包含一些特殊的请求头字段,分别可以获取一些额外信息,如请设置的规则等
    // ctx.method 获取和设置请求方法
    // ctx.req
    // ctx.res
  const {req, res} = ctx;
  const client = request((svrRes) => {
    // 由于内容长度可能有变,删除长度自动改成 chunked
    delete svrRes.headers['content-length'];
    delete req.headers['accept-encoding'];
    let body;
    svrRes.on('data', (data) => {
      body = body ? Buffer.concat([body, data]) : data;
    });
    svrRes.on('end', () => {
      try {
        // 获取到服务器返回体json格式,进行你想要的处理
        const jsonBody = JSON.parse(body.toString())
        const wrappedBody = {
            code: body.code || svrRes.statusCode,
            result: jsonBody
        }
        res.end(Buffer.from(JSON.stringify(wrappedBody)))
      } catch(e) {
        res.end(body);
      }      
    });
  });
  req.pipe(client);
};
shownstrong commented 3 months ago

感谢2位大佬解答。我现在发现正则也够用了,我这边的场景post的reqBody有1个id参数,我只针对这个参数写正则就行

avwo commented 1 month ago

requestBody

你代码有 bug,改成这个试试

// 转换请求体数据为字符串
const requestBodyString = (await requestBody).toString();
console.log('原始请求体数据长度:', requestBody.length);
console.log('原始请求体数据:', requestBodyString);