diff --git a/assets/js/phoenix/longpoll.js b/assets/js/phoenix/longpoll.js index 2ee739fac3..cc9c1d20fc 100644 --- a/assets/js/phoenix/longpoll.js +++ b/assets/js/phoenix/longpoll.js @@ -71,6 +71,13 @@ export default class LongPoll { this.ajax("GET", headers, null, () => this.ontimeout(), resp => { if(resp){ var {status, token, messages} = resp + if(status === 410 && this.token !== null){ + // In case we already have a token, this means that our existing session + // is gone. We fail so that the client rejoins its channels. + this.onerror(410) + this.closeAndRetry(3410, "session_gone", false) + return + } this.token = token } else { status = 0 diff --git a/assets/test/longpoll_test.js b/assets/test/longpoll_test.js index f02871a39f..4f190e1d77 100644 --- a/assets/test/longpoll_test.js +++ b/assets/test/longpoll_test.js @@ -83,11 +83,11 @@ describe("LongPoll", () => { const authToken = "my-auth-token" const encodedToken = btoa(authToken) const protocols = ["phoenix", `${AUTH_TOKEN_PREFIX}${encodedToken}`] - + const longpoll = new LongPoll("http://localhost/socket/longpoll", protocols) longpoll.timeout = 1000 longpoll.poll() - + // Verify Ajax.request was called with the correct headers expect(Ajax.request).toHaveBeenCalledWith( "GET", @@ -104,7 +104,7 @@ describe("LongPoll", () => { const longpoll = new LongPoll("http://localhost/socket/longpoll", undefined) longpoll.timeout = 1000 longpoll.poll() - + // Verify Ajax.request was called without auth token header expect(Ajax.request).toHaveBeenCalledWith( "GET", @@ -116,6 +116,27 @@ describe("LongPoll", () => { expect.any(Function) ) }) + + it("should treat 410 as error when token already exists", () => { + const longpoll = new LongPoll("http://localhost/socket/longpoll", undefined) + longpoll.timeout = 1000 + longpoll.token = "existing-token" + + const mockOnerror = jest.fn() + const mockCloseAndRetry = jest.fn() + longpoll.onerror = mockOnerror + longpoll.closeAndRetry = mockCloseAndRetry + + Ajax.request.mockImplementation((method, url, headers, body, timeout, ontimeout, callback) => { + callback({status: 410, token: "new-token", messages: []}) + return {abort: jest.fn()} + }) + + longpoll.poll() + + expect(mockOnerror).toHaveBeenCalledWith(410) + expect(mockCloseAndRetry).toHaveBeenCalledWith(3410, "session_gone", false) + }) }) describe("batchSend", () => {