使用http-proxy为Theia编辑器配置代理的WebSocket问题排查
Theia编辑器通过http-proxy代理后WebSocket连接问题排查与解决
我在6080端口运行Theia编辑器,直接访问localhost:6080时功能完全正常。搭建基于Node.js的http-proxy代理服务器,将5000端口请求转发至6080端口后,通过localhost:5000访问编辑器时页面可加载,但WebSocket连接失败,触发proxy.on('close')事件,控制台输出Client disconnected : 。
代理服务器代码(执行node app.js启动)
let http = require("http"); let httpProxy = require("http-proxy"); let proxy = new httpProxy.createProxyServer(); function getPortFromUrl(url) { return 6080; } var proxyServer = http.createServer(async function (req, res) { try { if (req.url === "/favicon.ico") { res.writeHead(204); res.end(); return; } // console.log("req.url : ", req.url); // NOTE: this logic of getting port I have simplified for DEMO purpose let uiPort = getPortFromUrl(req.url); if (!uiPort) { res.write("problem no port"); res.end(); return; } let targetUrl = "localhost" + ":" + uiPort + req.url.split("/").join("/"); // console.log("targetUrl : ", targetUrl); proxy.web( req, res, { target: `http://localhost:${uiPort}`, changeOrigin: true, ws: true, secure: false, }, function (e) { console.log(e); console.log("an error occured"); } ); } catch (exception) { console.error("Request URL: " + req.url + " " + exception + " exception"); res.statusCode = 500; res.statusMessage = exception; res.writeHead(500); res.end(); } }); // // Listen to the `upgrade` event and proxy the // WebSocket requests as well. // proxyServer.on("upgrade", function (req, socket, head) { let uiPort = getPortFromUrl(req.url); console.log("req.url ::", req.url , " targetUrl :: ", `ws://localhost:${uiPort}${req.url.split("/").join("/")}`); proxy.ws(req, socket, head, { target: `ws://localhost:${uiPort}${req.url.split("/").join("/")}`, }); }); proxy.on("error", function (err, req, res) { console.error(err); // res.writeHead(500, { "Content-Type": "text/html" }); // res.write(`Error`); // res.end(); }); proxy.on('close', function (res, socket, head) { // view disconnected websocket connections console.error('Client disconnected : ', socket); }); var server = proxyServer.listen("5000", function () { console.info("proxy server started on port 5000"); });
Theia应用的package.json配置
{ "private": true, "dependencies": { "@theia/markers": "next", "@theia/terminal": "next", "@theia/mini-browser": "next", "@theia/plugin": "next", "@theia/plugin-ext": "next", "@theia/plugin-ext-vscode": "next" }, "devDependencies": { "@theia/cli": "next" }, "scripts": { "prepare": "yarn run clean && yarn build && yarn run download:plugins", "clean": "theia clean", "build": "theia build", "start": "theia start /Users/pawankumarsingh/Projects/theia --hostname 0.0.0.0 --port 6080 --plugins=local-dir:plugins", "download:plugins": "theia download:plugins" }, "theiaPluginsDir": "plugins", "theiaPlugins": { "redhat.java":"https://open-vsx.org/api/redhat/java/linux-x64/1.14.2022122003/file/redhat.java-1.14.2022122003@linux-x64.vsix" }, "theiaPluginsExcludeIds": [ "ms-vscode.js-debug-companion", "vscode.extension-editing", "vscode.git", "vscode.git-ui", "vscode.github", "vscode.github-authentication", "vscode.microsoft-authentication" ] }
Theia编辑器启动步骤
- 执行
yarn安装依赖 - 执行
yarn build构建项目 - 执行
yarn start启动编辑器
问题解决过程
之前在Theia和http-proxy相关文档中查找解决方案收获有限,后续修改WebSocket代理逻辑如下:
proxyServer.on("upgrade", function (req, socket, head) { let uiPort = getPortFromUrl(req.url); proxy.ws(req, socket, head, { target: `ws://localhost:${uiPort}`, }); });
修改后编辑器可正常加载,但初始加载时仍会触发proxy.on('close')事件。最终确认:该事件触发是因为服务器在WebSocket握手完成后关闭连接,属于正常行为,并非代理或连接存在问题。
内容的提问来源于stack exchange,提问作者Pawan Singh
相关产品推荐
相关产品推荐

