简单的node.js代理通过将http服务器传递给http请求

Nik*_*lov 14 proxy http node.js

尝试通过创建一个简单的http代理服务器来了解有关node.js的更多信息.使用场景很简单:用户 - >代理 - >服务器 - >代理 - >用户

以下代码一直有效,直到最后一步.无法找到管道连接器输出回用户的方法.

#!/usr/bin/env node

var
    url = require('url'),
    http = require('http'),
    acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
    console.log('request ' + request.url);
    request.pause();
    var options = url.parse(request.url);
    options.headers = request.headers;
    options.method = request.method;
    options.agent = false;

    var connector = http.request(options);
    request.pipe(connector);
    request.resume();
//  connector.pipe(response); // doesn't work
//  connector.pipe(request); // doesn't work either
});
Run Code Online (Sandbox Code Playgroud)

使用tcpflow我看到来自浏览器的传入请求,然后是传出代理请求,然后是服务器响应回代理.不知何故,我无法将响应重新传输回浏览器.

使用管道实现此逻辑的正确方法是什么?

Jay*_*Jay 24

你不必'暂停',只需'管'即可

var connector = http.request(options, function(res) {
  res.pipe(response, {end:true});//tell 'response' end=true
});
request.pipe(connector, {end:true});
Run Code Online (Sandbox Code Playgroud)

http请求不会完成,直到你告诉它'结束';

  • {end:true}是一个很好的建议.10X.关于暂停,我仍然认为使用它更好.想象一下,用户使用HTTP POST上传大文件.当传出连接正在构建时,为什么他的文件会被缓冲在服务器的RAM中?如果出于某种原因这种传出连接是不可能的呢? (5认同)
  • 现代节点不再需要FWIW,`{end:true}` - 默认为'true`,所以如果你禁用,你只需要传递选项. (5认同)

Nik*_*lov 22

好.得到它了.

更新:NB!正如评论中所报告的那样,此示例不再起作用.最有可能是由于Streams2 API更改(节点0.9+)

管道返回客户端必须在连接器的回调内发生,如下所示:

#!/usr/bin/env node

var
    url = require('url'),
    http = require('http'),
    acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
    console.log('request ' + request.url);
    request.pause();
    var options = url.parse(request.url);
    options.headers = request.headers;
    options.method = request.method;
    options.agent = false;

    var connector = http.request(options, function(serverResponse) {
            serverResponse.pause();
            response.writeHeader(serverResponse.statusCode, serverResponse.headers);
            serverResponse.pipe(response);
            serverResponse.resume();
    });
    request.pipe(connector);
    request.resume();
});
Run Code Online (Sandbox Code Playgroud)

  • @rob,很可能这个例子不适用于新的Streams2 API.Streams2在节点0.9中作为beta引入,并在0.10分支中稳定.0.10于2013年3月发布 - 在此讨论后数月.所以,如果你真的想要更具建设性,而不是放-1,请修改新API的示例. (4认同)

kas*_*ndr 5

我使用这篇文章中的示例来代理 http/s 请求。面临cookie在某处丢失的问题。

因此,要解决此问题,您需要处理代理响应中的标头。

下面是工作示例:

const http = require('http');
const acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
  const req = service.request(options, function(res) {
      response.writeHead(res.statusCode, res.headers);
      return res.pipe(response, {end: true});
  });
  request.pipe(req, {end: true});
});
Run Code Online (Sandbox Code Playgroud)

  • 请求回调中的“响应”是什么?您从哪里发出“请求”? (2认同)