【问题标题】:socket hang up error with nodejsnodejs的套接字挂起错误
【发布时间】:2014-10-02 03:50:06
【问题描述】:

我想为我不是管理员的一些 XYZ 服务器设置代理。 然后我想对请求和响应标头进行一些分析,然后对请求和响应主体进行一些分析。 所以我使用http-proxy https://github.com/nodejitsu/node-http-proxy

这就是我正在做的事情:

  var proxy = httpProxy.createProxyServer();


  connect.createServer(
    connect.bodyParser(),
    require('connect-restreamer')(),
    function (req, res) {
      proxy.web(req, res, { target : 'XYZserver' });
    }
  ).listen(config.listenPort);

在 GET 请求之前一切都很好,但是每当发出带有诸如 POST、PATCH、PUT 等请求的请求时,我都会收到错误消息:

Error: socket hang up
    at createHangUpError (http.js:1472:15)
    at Socket.socketCloseListener (http.js:1522:23)
    at Socket.EventEmitter.emit (events.js:95:17)
    at TCP.close (net.js:466:12)

我用谷歌搜索了很多,但没有发现发生了什么问题。 我使用 'proxy.web' 的 'ws:true' 选项启用套接字代理,但仍然出现相同的错误。

【问题讨论】:

    标签: javascript node.js sockets proxy


    【解决方案1】:

    我在 postputdelete时遇到了这个问题>,但从 chimurai 阅读 this issue / http-proxy-middleware,我搞定了。
    1-添加onProxyReqhttps://github.com/chimurai/http-proxy-middleware/issues/40#issuecomment-249430255
    2- strong> 请注意,您必须在请求的标头中添加 Content-Type: application/json
    3- 正文解析器没有更改顺序

    【讨论】:

      【解决方案2】:

      在浪费了一天多的时间并关注了nodejitsu/node-http-proxy issues 中的一些帖子之后,感谢 riccardo.cardin,我能够使其正常工作。 我决定发布完整的示例以节省您的时间。 下面的示例使用服务器expressbody-parser(req.body 中间件)当然还有http-proxy 代理并将请求转发到第三方服务器。

      const webapitargetUrl = 'https://posttestserver.com/post.php'; 
      
      var bodyParser = require('body-parser');
      app.use(bodyParser.urlencoded({ extended: false }));
      app.use(bodyParser.json()); // support json encoded bodies
      
      var https = require('https');
        var stamproxy = httpProxy.createProxyServer({
            target: 'https://localhost:8888',
            changeOrigin: true,
            agent  : https.globalAgent, 
            toProxy : true,
            secure: false,
            headers: {
            'Content-Type': 'application/json'
            } 
          });
      
        stamproxy.on('proxyReq', function(proxyReq, req, res, options) {
            console.log("proxying for",req.url);
            if (req.body) {
              console.log("prxyReq req.body: ",req.body);
              // modify the request. Here i just by removed ip field from the request you can alter body as you want
              delete req.body.ip;
              let bodyData = JSON.stringify(req.body);
              // in case if content-type is application/x-www-form-urlencoded -> we need to change to application/json
              proxyReq.setHeader('Content-Type','application/json');
              proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
              // stream the content
              console.log("prxyReq bodyData: ",bodyData);
              proxyReq.write(bodyData);
            }
            console.log('proxy request forwarded succesfully');
        });
      
        stamproxy.on('proxyRes', function(proxyRes, req, res){    
          proxyRes.on('data' , function(dataBuffer){
              var data = dataBuffer.toString('utf8');
              console.log("This is the data from target server : "+ data);
          }); 
        });
      
      
      app.use(compression());
      app.use(favicon(path.join(__dirname, '..', 'static', 'favicon.ico')));
      
      app.use(Express.static(path.join(__dirname, '..', 'static')));
      
      
      var sessions = require("client-sessions");
      app.use(sessions({
        secret: 'blargadeeblargblarg',
        cookieName: 'mysession'
      }));
      
      app.use('/server/setserverip', (req, res) => {
      
          console.log('------------ Server.js /server/setserverip  ---------------------------------');
          req.mysession.serverip += 1;
      
          console.log('session data:');
          console.log(req.mysession.serverip)
          console.log('req.body:');
          console.log(req.body);
      
          // Proxy forwarding   
          stamproxy.web(req, res, {target: webapitargetUrl});
          console.log('After calling proxy serverip');
      
      });
      

      【讨论】:

        【解决方案3】:

        为了完整起见,body-parserhttp-proxy 模块之间确实存在集成问题,如 this 线程中所述。

        如果不能改变中间件的顺序;您可以在代理请求之前重新流式传输已解析的正文。

        // restream parsed body before proxying
        proxy.on('proxyReq', function(proxyReq, req, res, options) {
            if (req.body) {
                let bodyData = JSON.stringify(req.body);
                // incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
                proxyReq.setHeader('Content-Type','application/json');
                proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
                // stream the content
                proxyReq.write(bodyData);
            }
        }
        

        我在这个 f***** 问题上浪费了 2 天时间。希望对您有所帮助!

        【讨论】:

        • 你是英雄。
        • 您还可以更改中间件的顺序以使其工作
        • @ospider,答案从一个前置条件开始:“如果你不能改变中间件的顺序” :)
        【解决方案4】:

        http-proxy 似乎与body-parser 中间件不兼容。 您可能希望将 http-proxy 中间件移到 body-parser 之前,或者停止使用 body-parser

        另请参阅: Socket hangup while posting request to Node-http-proxy Node.js

        【讨论】:

          【解决方案5】:

          需要捕捉代理的错误:

          var httpProxy = require('http-proxy');
          var proxy = httpProxy.createProxyServer({ target: argv.proxy_url })
          
          proxy.on('error', function(err, req, res) {
              res.end();
          })
          

          【讨论】:

            【解决方案6】:

            我遇到了类似的问题,并通过将我的代理代码移动到其他节点中间件之上来解决它。

            例如这个:

            var httpProxy = require('http-proxy');
            var apiProxy = httpProxy.createProxyServer();
            app.use("/someroute", function(req, res) {
                apiProxy.web(req, res, { target: 'http://someurl.com'})
            });
            
            app.use(someMiddleware);
            

            不是这个:

            app.use(someMiddleware);
            
            var httpProxy = require('http-proxy');
            var proxy = httpProxy.createProxyServer();
            app.use("/someroute", function(req, res) {
                proxy.web(req, res, { target: 'http://someurl.com'})
            });
            

            我的具体问题是代理上方有 BodyParser 中间件。我没有做太多的挖掘工作,但它一定是以某种方式修改了请求,当请求最终到达时破坏了代理库。

            【讨论】:

            • 好的,但是如果你把body-parser放在代理使用之后你就不能修改请求的正文了:(
            • @Michael - 下面的代码可以正常工作吗? import BodyParser from 'body-parser'; var httpProxy = require('http-proxy'); var apiProxy = httpProxy.createProxyServer(); app.use("/someroute", function(req, res) { if (some conditions) { req.url = '/abc'; app.handle(req, res); } else { apiProxy.web(req, res, { target: 'http://someurl.com'}) } }); app.use(someMiddleware); app.use(compression()); const jsonParser = BodyParser.json(); app.post('/abc', jsonParser, (req, res) => { // some code res.send(some data); });
            猜你喜欢
            • 2015-09-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-04
            • 1970-01-01
            • 2014-10-06
            • 2021-07-29
            • 2013-10-05
            相关资源
            最近更新 更多