【问题标题】:Redirect async calls made by npm module "request" inside a nodejs express app重定向 nodejs express 应用程序中 npm 模块“请求”发出的异步调用
【发布时间】:2018-09-12 17:11:19
【问题描述】:

我想捕获“请求”发出的异步调用。
我要拦截的电话是 "https://api.ap.org/v2/yada/yada" 。

我想拦截对 api.ap.org 的第三方调用并将其重定向到另一个服务,例如 127.0.0.1:3001。

我还想在这个拦截过程中添加标头。

我知道如何拦截 express js 路由通过 http-proxy 进行的所有调用,但这不会拦截 nodejs 本身内部进行的调用。

 router.get('/', function(req, res, next) {
   request("https://api.ap.org/v2/yada/yada", {}, (err, data) => {
       console.log('---- call made')
       console.log(data);
    });
   res.render('index', { title: 'Express' });
 });

更新 - 来自 Estus

function patchedRequest(url, options, ...args) {
  let newUrl = 'https://www.google.com/' // replace url with another one;
  console.log('------ args');
  console.log(url);
  console.log(options);
  if(url.match(/api\.ap\.org/).length){
      options = {};
      newUrl = 'http://127.0.0.1:3000/api'
  }
  return originalRequest(newUrl, options, ...args);
}
  • 这允许我拦截对第三方 API 的调用并将其发送给我选择的服务。

感谢埃斯图斯!

【问题讨论】:

  • 这不会拦截在 nodejs 本身内进行的调用 - 究竟什么不起作用?回调没有被调用吗?
  • 长话短说,我无法更改此应用程序中的代码。我只能添加一个外部应用程序或将一些代码添加到条目“app.js”文件中。对第三方端点进行了数千次调用。我需要重定向所有这些,但我使用 api.ap.org 作为起点。
  • 您可以模拟request,使用rewire 或其他东西。或全局代理节点请求,stackoverflow.com/questions/18586902/…。或者为 requestgithub.com/request/… 指定一个代理。实际的解决方案取决于您的情况是如何完成的。
  • "request" 需要数千次。每个 require 都是一个新实例。我不认为“请求”使他们的模块成为单例。我将不得不分叉回购并在“请求”模块中添加一个钩子并使用我的叉子。我尝试将 nginx 用作非透明转发代理,但也遇到了问题。
  • request 本身就是一个单例。 JS 模块根据定义是单例的。 require('request') === require('request')。您可以使用 proxyquire 创建一个包装器(我不认为 rewire 可以完成这项工作),或者不要分叉 request

标签: node.js express


【解决方案1】:

这可以通过模拟原始 request 模块来完成。

这大致就是像proxyquire 这样的缓存修改库的工作方式:

patch-request.js

const originalRequest = require('request');

function patchedRequest(url, ...args) {
  const newUrl = 'https://www.google.com/' // replace url with another one;
  return originalRequest(newUrl, ...args);
}

Object.assign(patchedRequest, originalRequest);

for (const verb of 'get,head,options,post,put,patch,del,delete'.split(',')) {
  patchedRequest[verb] = function (url, ...args) {
    const newUrl = 'https://www.google.com/' // replace url with another one;
    return originalRequest[verb](newUrl, ...args);
  };
}

module.exports = require.cache[require.resolve('request')].exports = patchedRequest;

index.js

// patch request before it's required anywhere else
require('./patch-request');

// load the app that uses request

【讨论】:

  • 我认为你的男人!我尝试了许多不同的角度,这是最简单的解决方案。 - 用您的答案更新问题
  • 干得好...这也只是为了我正在创建的测试工具。它不会向公众发布或需要证券。
  • 不客气。代理服务器可能是更灵活和透明的解决方案,尽管它需要关心更多的事情。至于测试,如果可能的话,在应用程序中将require('request') 替换为rewire('request'),这就是rewire 的用途。
  • 是的,我直到今天结束才得到解决这个问题,然后我要去其他不太绿色的牧场哈哈。我有一个技术债务故事要回来并提出一个更清洁的解决方案。再次感谢您的帮助
  • 我明白了。答案中的解决方案可以作为常规解决方案,也可以作为快速解决方案,我想这符合您的需求。
猜你喜欢
  • 2018-05-04
  • 2012-06-19
  • 2019-06-21
  • 1970-01-01
  • 2017-01-06
  • 1970-01-01
  • 2017-03-09
  • 2016-08-21
  • 2017-11-14
相关资源
最近更新 更多