You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中HTTPS转HTTP的WebSocket请求代理问题排查

解决Node.js代理服务器HTTPS客户端WebSocket请求失败问题

问题根源分析

你的核心问题出在两个关键点:

  1. changeOrigin配置逻辑错误:当前代码根据目标URL是否为localhost决定是否开启changeOrigin,但实际需求是根据客户端请求是否来自HTTPS环境来判断——云HTTPS网站的请求需要修改Host头匹配本地端点,而本地HTTP网站则不需要。
  2. WebSocket代理未明确禁用TLS:当客户端是HTTPS时,http-proxy会默认尝试用wss://协议连接目标,但你的目标是HTTP端点,导致TLS握手失败,触发连接断开错误。

修复方案

1. 动态调整changeOrigin配置

根据客户端请求的协议(直接HTTPS或反向代理后的X-Forwarded-Proto头)决定是否开启changeOrigin,确保本地端点收到正确的Host头。

2. WebSocket代理强制禁用TLS

在upgrade事件处理中,明确设置secure: false,强制代理使用ws://协议连接HTTP目标端点,避免不必要的TLS握手。

完整修改代码

import * as express from "express";
import { Server, createServer } from "http";
import { createProxyServer } from "http-proxy";
import { settings } from "./settings"

export let port = 3004;

let server: Server;

// 判断客户端是否为HTTPS请求的工具函数
function isClientHttps(req: express.Request): boolean {
  // 直接HTTPS请求或反向代理转发的HTTPS请求
  return req.secure || req.headers['x-forwarded-proto'] === 'https';
}

export function startServer() {
    const targetURL = settings.URL;
    const app = express();
    server = createServer(app);

    const proxy = createProxyServer({
        target: targetURL,
        ws: true,
        headers: {
            // 自定义请求头
        },
    });

    server.on("upgrade", function (req, socket, head) {
        proxy.ws(req, socket, head, {
            changeOrigin: isClientHttps(req),
            secure: false // 强制禁用TLS,适配HTTP目标端点
        });
    });

    // 所有路由统一处理,避免重复代码
    app.use(["/public/*", "/api/*", "/api/query"], function (req, res) {
        proxy.web(req, res, {
            changeOrigin: isClientHttps(req)
        });
    });

    server.listen(0, () => {
        port = server?.address()?.port;
        console.log(`Server started on port ${port}`);
    });
}

export function stopServer() {
    if (server) {
        server.close();
    }
}

额外说明

如果你的代理需要直接接收HTTPS请求(而非通过反向代理),需要额外创建HTTPS服务器并监听upgrade事件:

import * as https from 'https';
import * as fs from 'fs';

// 加载SSL证书文件
const sslOptions = {
  key: fs.readFileSync('./private-key.pem'),
  cert: fs.readFileSync('./certificate.pem')
};

// 创建HTTPS服务器
const httpsServer = https.createServer(sslOptions, app);
httpsServer.on("upgrade", function (req, socket, head) {
    proxy.ws(req, socket, head, {
        changeOrigin: true, // HTTPS客户端默认开启changeOrigin
        secure: false
    });
});

httpsServer.listen(443, () => console.log('HTTPS proxy running on port 443'));

内容的提问来源于stack exchange,提问作者Clarity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:23:14