Skip to content

Commit 8f1ea3d

Browse files
fix: handle aborted requests
Previously, an aborted request (for example, when the user closes its tab) would not close the session right away and would simply time out upon the next failed heartbeat.
1 parent 4150b2b commit 8f1ea3d

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

lib/transports/polling.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class Polling extends Transport {
3838
* @private
3939
*/
4040
private onPollRequest(
41-
_req: Request,
41+
req: Request,
4242
responseHeaders: Headers,
4343
): Promise<Response> {
4444
if (this.pollingPromise) {
@@ -51,6 +51,10 @@ export class Polling extends Transport {
5151

5252
debug("new polling request");
5353

54+
req.signal.addEventListener("abort", () => {
55+
this.onError("polling request aborted");
56+
});
57+
5458
return new Promise<Response>((resolve, reject) => {
5559
this.pollingPromise = { resolve, reject, responseHeaders };
5660

@@ -72,6 +76,10 @@ export class Polling extends Transport {
7276
): Promise<Response> {
7377
debug("new data request");
7478

79+
req.signal.addEventListener("abort", () => {
80+
this.onError("data request aborted");
81+
});
82+
7583
const data = await req.text();
7684

7785
if (data.length > this.opts.maxHttpBufferSize) {

test/engine.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ async function initLongPollingSession() {
1414
return JSON.parse(content.substring(1)).sid;
1515
}
1616

17+
// imported from https://github.com/socketio/socket.io/blob/main/docs/engine.io-protocol/v4-test-suite
1718
describe("Engine.IO protocol", () => {
1819
beforeAll(() => {
1920
const engine = new Server({
@@ -313,6 +314,25 @@ describe("Engine.IO protocol", () => {
313314

314315
expect(pollResponse.status).toEqual(400);
315316
});
317+
318+
it("closes the session upon cancelled polling request", async () => {
319+
const sid = await initLongPollingSession();
320+
const controller = new AbortController();
321+
322+
fetch(`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`, {
323+
signal: controller.signal,
324+
}).catch(() => {});
325+
326+
await sleep(5);
327+
328+
controller.abort();
329+
330+
const pollResponse = await fetch(
331+
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
332+
);
333+
334+
expect(pollResponse.status).toEqual(400);
335+
});
316336
});
317337

318338
describe("WebSocket", () => {

test/socket.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ async function initSocketIOConnection() {
2525
return socket;
2626
}
2727

28+
// imported from https://github.com/socketio/socket.io/tree/main/docs/socket.io-protocol/v5-test-suite
2829
describe("Socket.IO protocol", () => {
2930
beforeAll(() => {
3031
const io = new Server();

0 commit comments

Comments
 (0)