node.js实现反向代理到源服务器的HTTP2协议

发布时间 2023-05-07 02:28:30作者: 项希盛

node.js实现反向代理到源服务器的HTTP2协议

const tls = require('tls');
const http = require('http');
const http2 = require('http2');
const {
  HTTP2_HEADER_AUTHORITY,
  HTTP2_HEADER_METHOD,
  HTTP2_HEADER_PATH,
  HTTP2_HEADER_STATUS,
} = http2.constants;

const server = http.createServer();

let sharedConnection = null;

function createSharedConnection(sUrl) {
  const client = http2.connect(sUrl, {
    createConnection: (mUrl) => {
      const options = {};
      options.host = mUrl.hostname;
      options.port = mUrl.port;
      options.servername = 'fpw.feieryun.cn';
      options.ALPNProtocols = ['h2'];
      return tls.connect(options);
    }
  });

  client.on('connect', () => console.log('http2 client connect success'));
  client.on('error', (err) => {
    console.error(`http2 client connect error: ${err}`);
    if (err.code === 'ECONNRESET') {
      console.log('Connection reset, reconnecting...');
      // 断线后自动重连
      createSharedConnection(sUrl);
    }
  });
  sharedConnection = client;
}
createSharedConnection('https://47.90.101.1:379');

server.on('request', (req, res) => {

  // 向 HTTP/2 服务发送请求
  const reqOptions = req.headers;
  delete reqOptions.connection;
  reqOptions[HTTP2_HEADER_AUTHORITY] = 'www.28820.com';
  reqOptions[HTTP2_HEADER_METHOD] = req.method;
  reqOptions[HTTP2_HEADER_PATH] = req.url;

  try {
    const proxyReq = sharedConnection.request(reqOptions);
    req.pipe(proxyReq);
    proxyReq.pipe(res);
    proxyReq.on('response', (headers) => {
      // 将 HTTP/2 服务的响应转发给客户端
      const statusCode = headers[HTTP2_HEADER_STATUS];
      delete headers[HTTP2_HEADER_STATUS];
      res.writeHead(statusCode, headers);
    });
  } catch (ex) {
    console.error('request.error', ex);
    res.writeHead(500);
    res.end('HTTP/500 Bad Gateway');
  }

});

server.listen(8080, () => {
  console.log('HTTP server listening on port 8080');
});