mirror of
https://github.com/actions/runner.git
synced 2026-01-23 13:01:14 +08:00
fix ws proxy corrupting responses
This commit is contained in:
@@ -74,7 +74,7 @@ wss.on('connection', (ws, req) => {
|
||||
port: config.dapPort,
|
||||
});
|
||||
|
||||
let tcpBuffer = '';
|
||||
let tcpBuffer = Buffer.alloc(0);
|
||||
let tcpConnected = false;
|
||||
|
||||
tcp.on('connect', () => {
|
||||
@@ -135,33 +135,45 @@ wss.on('connection', (ws, req) => {
|
||||
});
|
||||
|
||||
// TCP → WebSocket: Parse Content-Length framing
|
||||
// IMPORTANT: We use Buffer (byte-based) operations because DAP's Content-Length
|
||||
// header specifies the message length in bytes, not characters. Using string
|
||||
// operations would cause buffer misalignment when the JSON contains multi-byte
|
||||
// UTF-8 characters.
|
||||
tcp.on('data', (chunk) => {
|
||||
tcpBuffer += chunk.toString();
|
||||
// Append chunk to buffer (chunk is already a Buffer)
|
||||
tcpBuffer = Buffer.concat([tcpBuffer, chunk]);
|
||||
|
||||
// Process complete DAP messages from buffer
|
||||
const headerEndMarker = Buffer.from('\r\n\r\n');
|
||||
|
||||
while (true) {
|
||||
// Look for Content-Length header
|
||||
const headerEnd = tcpBuffer.indexOf('\r\n\r\n');
|
||||
// Look for header end (\r\n\r\n)
|
||||
const headerEnd = tcpBuffer.indexOf(headerEndMarker);
|
||||
if (headerEnd === -1) break;
|
||||
|
||||
const header = tcpBuffer.substring(0, headerEnd);
|
||||
// Extract header as string to parse Content-Length
|
||||
const header = tcpBuffer.slice(0, headerEnd).toString('utf8');
|
||||
const match = header.match(/Content-Length:\s*(\d+)/i);
|
||||
if (!match) {
|
||||
console.error(`[Proxy] Invalid DAP header: ${header}`);
|
||||
tcpBuffer = tcpBuffer.substring(headerEnd + 4);
|
||||
// Skip past the invalid header
|
||||
tcpBuffer = tcpBuffer.slice(headerEnd + 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
const contentLength = parseInt(match[1]);
|
||||
const messageStart = headerEnd + 4;
|
||||
const contentLength = parseInt(match[1], 10);
|
||||
const messageStart = headerEnd + 4; // After \r\n\r\n
|
||||
const messageEnd = messageStart + contentLength;
|
||||
|
||||
// Check if we have the complete message
|
||||
// Check if we have the complete message (in bytes)
|
||||
if (tcpBuffer.length < messageEnd) break;
|
||||
|
||||
// Extract the JSON message
|
||||
const json = tcpBuffer.substring(messageStart, messageEnd);
|
||||
tcpBuffer = tcpBuffer.substring(messageEnd);
|
||||
// Extract the JSON message (as bytes, then decode to string)
|
||||
const jsonBuffer = tcpBuffer.slice(messageStart, messageEnd);
|
||||
const json = jsonBuffer.toString('utf8');
|
||||
|
||||
// Remove processed message from buffer
|
||||
tcpBuffer = tcpBuffer.slice(messageEnd);
|
||||
|
||||
// Send to WebSocket
|
||||
try {
|
||||
@@ -175,6 +187,7 @@ wss.on('connection', (ws, req) => {
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[Proxy] Invalid JSON from TCP: ${err.message}`);
|
||||
console.error(`[Proxy] JSON content (first 200 chars): ${json.substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user