【问题标题】:Hapi.js Proxy - change the response before replyHapi.js 代理 - 在回复之前更改响应
【发布时间】:2020-11-19 17:55:25
【问题描述】:

我正在尝试为我正在处理的一个新项目测试 Hapi.js 我的目标是在我的 Hapi 服务器上触发一个请求,这个请求将在使用 Hapi 代理的远程服务器上触发另一个请求,并且响应将只是来自远程响应的特定属性

要对此进行测试,必须向 /api/type3/name 发出请求,这将调用对 GitHub 的 API 的 API 调用以获取用户对象

代码:

server.route({
    method: 'GET',
    path: '/api/type3/{name}',
    handler: {
      proxy: {
        mapUri: function(request,callback){
            callback(null,'https://api.github.com/users/'+request.params.name);
        },
        onResponse: function(err, res, request, reply, settings, ttl){
           console.log(res); 
           reply(res);
        },
        passThrough: true,
        xforward: true
      }
    }
});

上述代码的响应是来自GitHub的响应对象 现在我需要保存这个响应,以便我可以操纵它并只返回我需要的内容

但是当我调试响应对象时,它包含大量数据,我无法在其中找到响应负载

那么如何从响应对象中只提取来自 GitHub 的响应呢?

非常感谢

【问题讨论】:

  • 在启动节点进程之前设置 NODE_DEBUG 环境变量,以了解更多是否仍然看不到响应缓冲区。例如``` export NODE_DEBUG=http,stream,net``` 或者只是http日志export NODE_DEBUG=http

标签: javascript node.js hapijs


【解决方案1】:

res 对象是一个http.IncomingMessage。如果您想使用响应的正文,您需要先从其中读取所有数据。

您有 2 个选择。

1) 普通节点

onResponse: function(err, res, request, reply, settings, ttl){

    var body = '';

    res.on('data', function (chunk) {
        body += chunk;
    });

    res.on('end', function () {
        console.log(body);  
        reply(body);
    });
}

2) 使用 Wreck(Hapi 人制作的用于在 Node 中使用 HTTP 的模块)

var Wreck = require('wreck');

onResponse: function(err, res, request, reply, settings, ttl){
   Wreck.read(res, null, function (err, payload) {
       console.log(payload);
       reply(payload);
   });
}

【讨论】:

  • 两种选择都返回了实际的缓冲区,但我未能从缓冲区中获取实际数据,但是我现在将更多地研究 wreck 以了解它如何提供帮助
  • 也许您没有从上游服务器获取有效负载。你检查过err 和或res.statusCode吗?
  • @MattHarrison Wreck documentation 显示了一个强制性的第二个参数 Wreck.read(response, options, callback)。代码审查确认。自您的回答以来,这是一个变化吗?
  • @glenschler 不,这是一个错误。我已经更新了我的答案,谢谢!
  • 只有在acceptEncoding: false设置完成后才有效。
【解决方案2】:

在上面的沉船案例中,你可以这样做

payload = payload.toString();

将缓冲区转换为实际数据。

【讨论】:

    【解决方案3】:

    我想从远程服务器加载 xml 数据并将响应转换为 json。 该线程帮助我找到了适合我的解决方案。但在我的情况下,上面的代码也不起作用,因为来自远程服务器的响应被压缩了。在我的控制台中只有不可读的数据。

    我尝试为代理启用自动负载解析,但没有成功。最后我不得不自己用'zlib'解压缩响应。

    这段代码对我有用:

    'use strict'
    
    const url = require('url')
    const h2o2 = require('h2o2')
    const Hapi = require('hapi')
    const parseString = require('xml2js').parseString
    var zlib = require('zlib')
    const _ = require('lodash')
    
    var remoteServerUrl = 'http://some-url.com:2434'
    var originUrl = 'http://localhost:3000'
    
    // Create a server with a host and port
    const server = new Hapi.Server()
    server.connection({
      host: 'localhost',
      port: 3001,
      routes: {
        cors: {
          origin: [originUrl],
        },
      },
    })
    
    server.register({
      register: h2o2,
    }, function (err) {
      server.start(function (err) {
        console.log('Proxy Server started at: ' + server.info.uri)
      })
    })
    
    server.route({
      method: '*',
      path: '/proxy/{path*}',
    
      config: {
        payload: {
          // parse: true,   // didn't worked for me
          // parse: 'gzip', // didn't worked for me
          output: 'stream',
        },
      },
    
      handler: {
    
        proxy: {
          passThrough: true,
          timeout: 15000,
          acceptEncoding: false,
    
          mapUri (request, callback) {
            callback(null, url.format({
              protocol: url.parse(remoteServerUrl).protocol,
              host: url.parse(remoteServerUrl).host,
              port: url.parse(remoteServerUrl).port,
              pathname: request.params.path,
              query: request.query,
            }))
          },
    
          onResponse (err, res, request, reply, settings, ttl) {
            if (err) {
              console.error('Hapi server error: ', err)
            }
    
            // let's unzip the response 
            var gunzip = zlib.createGunzip()
            var xmlStr = ''
    
            gunzip.on('data', function (data) {
              xmlStr += data.toString()
            })
    
            gunzip.on('end', function () {
              // do something with the string
              // in this case convert xml to json string
              parseString(xmlStr, {}, function (err, result) {
                // send result back
                reply(result)
              })
            })
    
            res.pipe(gunzip)
          },
        },
      },
    })
    

    也许这对其他人有帮助;)

    【讨论】:

      猜你喜欢
      • 2016-12-09
      • 1970-01-01
      • 2018-12-31
      • 2013-08-09
      • 2020-07-21
      • 2021-08-02
      • 2021-04-07
      • 1970-01-01
      • 2016-02-11
      相关资源
      最近更新 更多