Skip to content

Commit e29eed3

Browse files
committed
fix: capture transport reference at request time to fix response routing
The Protocol class was overwriting its transport reference when new clients connected, causing responses to be sent to the wrong transport. This fix captures the transport reference when a request arrives and uses that captured reference throughout the request lifecycle. This ensures: - Each request's response is sent back through the correct transport - Multiple clients can connect without interfering with each other - Async request handling works correctly even when new connections arrive
1 parent f997f86 commit e29eed3

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

src/shared/protocol-transport-handling.test.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,24 +102,23 @@ describe("Protocol transport handling bug", () => {
102102
console.log("Transport A received:", transportA.sentMessages);
103103
console.log("Transport B received:", transportB.sentMessages);
104104

105-
// BUG: The response for client A's request will be sent to transport B
106-
// because the protocol's transport reference was overwritten
105+
// FIXED: Each transport now receives its own response
107106

108-
// What happens (bug):
109-
// - Transport A should have received the response for request ID 1, but it's empty
110-
expect(transportA.sentMessages.length).toBe(0);
111-
112-
// - Transport B incorrectly receives BOTH responses
113-
expect(transportB.sentMessages.length).toBe(2);
114-
expect(transportB.sentMessages[0]).toMatchObject({
107+
// Transport A should receive response for request ID 1
108+
expect(transportA.sentMessages.length).toBe(1);
109+
expect(transportA.sentMessages[0]).toMatchObject({
115110
jsonrpc: "2.0",
116-
id: 1, // This is A's request ID!
111+
id: 1,
117112
result: { data: "responseForA" }
118113
});
119114

120-
// What SHOULD happen (after fix):
121-
// - Transport A should receive response for request ID 1
122-
// - Transport B should receive response for request ID 2
115+
// Transport B should only receive its own response (when implemented)
116+
expect(transportB.sentMessages.length).toBe(1);
117+
expect(transportB.sentMessages[0]).toMatchObject({
118+
jsonrpc: "2.0",
119+
id: 2,
120+
result: { data: "responseForA" } // Same handler result in this test
121+
});
123122
});
124123

125124
test("demonstrates the timing issue with multiple rapid connections", async () => {
@@ -183,8 +182,8 @@ describe("Protocol transport handling bug", () => {
183182

184183
console.log("Timing test results:", results);
185184

186-
// BUG: All responses go to transport B
187-
expect(transportA.sentMessages.length).toBe(0);
188-
expect(transportB.sentMessages.length).toBe(2); // Gets both responses
185+
// FIXED: Each transport receives its own responses
186+
expect(transportA.sentMessages.length).toBe(1);
187+
expect(transportB.sentMessages.length).toBe(1);
189188
});
190189
});

src/shared/protocol.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,11 @@ export abstract class Protocol<
367367
const handler =
368368
this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
369369

370+
// Capture the current transport at request time to ensure responses go to the correct client
371+
const capturedTransport = this._transport;
372+
370373
if (handler === undefined) {
371-
this._transport
374+
capturedTransport
372375
?.send({
373376
jsonrpc: "2.0",
374377
id: request.id,
@@ -390,7 +393,7 @@ export abstract class Protocol<
390393

391394
const fullExtra: RequestHandlerExtra<SendRequestT, SendNotificationT> = {
392395
signal: abortController.signal,
393-
sessionId: this._transport?.sessionId,
396+
sessionId: capturedTransport?.sessionId,
394397
_meta: request.params?._meta,
395398
sendNotification:
396399
(notification) =>
@@ -411,7 +414,7 @@ export abstract class Protocol<
411414
return;
412415
}
413416

414-
return this._transport?.send({
417+
return capturedTransport?.send({
415418
result,
416419
jsonrpc: "2.0",
417420
id: request.id,
@@ -422,7 +425,7 @@ export abstract class Protocol<
422425
return;
423426
}
424427

425-
return this._transport?.send({
428+
return capturedTransport?.send({
426429
jsonrpc: "2.0",
427430
id: request.id,
428431
error: {

0 commit comments

Comments
 (0)