【问题标题】:How to proxy request to h2c HTTP/2 server with sockets?如何使用套接字将请求代理到 h2c HTTP/2 服务器?
【发布时间】:2018-12-13 08:31:09
【问题描述】:

这一定是个简单的问题,但我对流的了解有限。

HTTP/1 80 转 HTTP/2 h2c 代理

脚本(不工作):

const net = require('net');
const http = require('http');
const http2 = require('http2');
const socketPath = `/tmp/socket.test.${Date.now()}`;

// front http 80 server.
http.createServer((req, res) => {
    const socket = net.createConnection(socketPath)
    req.pipe(socket).pipe(res);
}).listen(80);

// private http2 socket server.
http2.createServer(function(socket) {
    socket.write(`Echo from http2 server\r\n`);
    socket.pipe(socket);
}).listen(socketPath);

HTTP/2 h2c 到 HTTP/2 h2c 代理

cli 命令启动请求:

curl --http2-prior-knowledge -v http://localhost:3333/ --output -

脚本(不工作):

const net = require('net');
const http = require('http');
const http2 = require('http2');
const socketPath = `/tmp/socket.test.${Date.now()}`;
const port = 3333;

const private = http2.createServer({allowHTTP1: true});
private.on('stream', (stream, headers) => {
    console.log('private http2 request');
    stream.end('HTTP/2');
});
private.listen(socketPath, () => console.log('private http2 server is listening', socketPath));

const public = http2.createServer({allowHTTP1: true});
public.on('stream', (stream, headers) => {
    console.log('public http2 request');
    const socket = net.connect(socketPath);
    stream.pipe(socket).pipe(stream);
});
public.listen(port, () => console.log('public http2 server is listening port', port));

【问题讨论】:

    标签: node.js http2


    【解决方案1】:

    终于,http2(h2c) 到 http2(h2c)(使用 unix 套接字)代理可以工作了!

    const net = require('net');
    const http2 = require('http2');
    const socketPath = `/tmp/socket.test.${Date.now()}`;
    const port = 4444;
    
    const priv = http2.createServer({});
    priv.on('stream', (stream, headers) => {
        console.log('private http2 request');
        stream.end('HTTP/2');
    });
    priv.listen(socketPath, () => console.log('private http2 server is listening', socketPath));
    
    const pub = http2.createServer({});
    pub.on('stream', (stream, headers) => {
        const clientSession = http2.connect('http://0.0.0.0', {
            createConnection: () => net.connect({path: socketPath})
        });
        const req = clientSession.request({
          ':path': `/`,
        });
        req.pipe(stream).pipe(req);
    });
    pub.listen(port, () => console.log('public http2 server is listening port', port));
    

    【讨论】:

      【解决方案2】:

      我不是节点专家,我可能完全误解了你在这里想要做什么,但我真的很难理解这个问题......

      如果您试图让 Node 充当 HTTP/2 代理(因此客户端可以通过 h2c 连接到节点并将这些详细信息传递给另一个 HTTP/2 感知服务器),那么您将采用的方式看起来……至少可以说很奇怪。

      代理可以是 4 级代理(例如 TCP 代理),它创建两个单独的 TCP 连接(一个从客户端到代理,一个从代理到目标服务器)并在它们之间发送这些 TCP 数据包的连接没有真正检查或干扰它们,除了 TCP 标头。

      代理可以是 7 级代理(例如 HTTP 代理),它创建两个单独的 HTTP 连接(一个从客户端到代理,一个从代理到目标服务器)并在它们之间发送 HTTP 消息,映射HTTP 标头和它们之间的详细信息,有时会更改详细信息甚至添加更多标头(例如 X-FORWARDED-FOR)。

      您似乎试图在这两种截然不同且不兼容的工作模式之间创建某种混合体!您希望创建一个 HTTP 或 HTTP/2 服务器,然后打开一个 TCP 套接字并在它们之间传递这些 TCP 消息并希望这可行?虽然这可能适用于像 HTTP/1 这样的简单协议,但它永远不会适用于 HTTP/2!

      对于您的第一个示例,HTTP/1 实例与 HTTP/2 完全不同。因此,从一开始就设置这两个并期望它们工作是有缺陷的。如果您的一个朋友只说德语而另一位朋友只说西班牙语,而您将所有德语信息逐字传递、未经过滤且仍然是德语的,那么您会期望说西班牙语的人能够神奇地理解它们吗?当然不是!因此,您不能在套接字级别连接 HTTP/1 和 HTTP/2 - 它们是完全不同的协议。您需要您的代理人充当他们之间的翻译。

      在您的第二个示例中,我更加困惑。我猜你正在尝试创建两个 HTTP/2 服务器,让客户端连接到一个,然后代理请求到另一个?并且大概您会在某个阶段在那里添加一些逻辑,因此只有某些请求才能通过,否则这将毫无意义。无论如何,这几乎肯定行不通。 HTTP/2 是一个复杂的协议,在许多方面更类似于 TCP。所以每个数据包都需要被赋予一个唯一的流 id,并且需要在两个端点之间协商许多其他设置。因此,假设一个 HTTP/2 消息将在另一个 HTTP/2 连接上无缝转换为相同的 HTTP/2 消息是非常幼稚的!回到语言类比,将德语信息逐字复制给另一位可能有听力障碍但坐得离您较近的德语使用者,最初可能会起作用,但一旦一端跟不上,讲一种稍微不同的方言,或者要求您重复他们错过的东西,整个节目就会崩溃。

      我建议您要么将其设为 4 级代理(因此忽略 HTTP 和 HTTP/2 并仅使用套接字),要么您希望将其设为 HTTP 代理(在这种情况下,接收每条 HTTP 消息,阅读它,并在下游连接上发送类似的 HTTP 消息)。你不能两者兼得。

      我也会质疑为什么以及是否需要这样做? HTTP/2 并未得到普遍支持,并且在客户端和边缘服务器(在这种情况下为代理)之间获得了大部分收益,那么您为什么觉得有必要一直讲 HTTP/2 呢?有关详细信息,请参阅此问题:HTTP/2 behind reverse proxy

      如果我完全误解了您的问题或您的意图,希望对您有所帮助并道歉!

      【讨论】:

      • 有 HTTP CONNECT 方法,它可以允许代理建立和暴露一个到服务器的 TCP 连接。这是一种“滥用”HTTP 代理来做比 L7 更多的事情的方法。
      • 这是真的,可能应该提到它,尽管这不是 OP 似乎想要在这里做的(尽管我承认我仍然有点困惑他们到底想要什么去做!!)。此外,我不确定我是否会称其为“滥用”,因为这正是 CONNECT 的目的。
      猜你喜欢
      • 2012-02-29
      • 2016-10-16
      • 2013-03-07
      • 1970-01-01
      • 2015-06-06
      • 2019-08-06
      • 2012-09-22
      • 1970-01-01
      • 2022-01-13
      相关资源
      最近更新 更多