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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13472024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:41:13  来源:igfitidea点击:

Simple node.js proxy by piping http server to http request

node.jshttpproxy

提问by Nikolai Gorchilov

Trying to learn more about node.js by making a simple http proxy server. The use scenario is simple: user -> proxy -> server -> proxy -> user

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

The following code works until the last step. Couldn't find way to pipe connector's output back to the user.

以下代码工作到最后一步。找不到将连接器的输出通过管道返回给用户的方法。

#!/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
});

Using tcpflow I see the incoming request from the browser, then the outgoing proxy request, then the server response back to the proxy. Somehow i couldn't manage to retransmit the response back to the browser.

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

What is the proper way to implement this logic with pipes?

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

回答by Jay

you dont have to 'pause', just 'pipe' is ok

您不必“暂停”,只需“管道”即可

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

http request will not finish until you tell it is 'end';

http 请求将不会完成,直到您告诉它“结束”;

回答by Nikolai Gorchilov

OK. Got it.

好的。知道了。

UPDATE: NB! As reported in the comments, this example doesn't work anymore. Most probably due to the Streams2 API change (node 0.9+)

更新:注意!如评论中所述,此示例不再有效。很可能是由于 Streams2 API 更改(节点 0.9+)

Piping back to the client has to happen inside connector's callback as follows:

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

#!/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();
});

回答by kashesandr

I used the examples from this post to proxy http/s requests. Faced with the problem that cookies were lost somewhere.

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

So to fix that you need to handle headers from the proxy response.

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

Below the working example:

在工作示例下方:

req = service.request(options, function(res) {
    response.writeHead(res.statusCode, res.headers);
    return res.pipe(response, {end: true});
});
request.pipe(req, {end: true});