diff --git a/spec/integ/matrix-client-opts.spec.js b/spec/integ/matrix-client-opts.spec.js index 606674e4d..7c256fd58 100644 --- a/spec/integ/matrix-client-opts.spec.js +++ b/spec/integ/matrix-client-opts.spec.js @@ -3,6 +3,7 @@ import HttpBackend from "matrix-mock-request"; import {MatrixClient} from "../../src/matrix"; import {MatrixScheduler} from "../../src/scheduler"; import {MemoryStore} from "../../src/store/memory"; +import {MatrixError} from "../../src/http-api"; describe("MatrixClient opts", function() { const baseUrl = "http://localhost.or.something"; @@ -132,10 +133,10 @@ describe("MatrixClient opts", function() { }); it("shouldn't retry sending events", function(done) { - httpBackend.when("PUT", "/txn1").fail(500, { + httpBackend.when("PUT", "/txn1").fail(500, new MatrixError({ errcode: "M_SOMETHING", error: "Ruh roh", - }); + })); client.sendTextMessage("!foo:bar", "a body", "txn1").then(function(res) { expect(false).toBe(true, "sendTextMessage resolved but shouldn't"); }, function(err) { diff --git a/src/http-api.js b/src/http-api.js index 99a889eb6..bce0534ed 100644 --- a/src/http-api.js +++ b/src/http-api.js @@ -276,6 +276,9 @@ MatrixHttpApi.prototype = { callbacks.clearTimeout(xhr.timeout_timer); var resp; try { + if (xhr.status === 0) { + throw new AbortError(); + } if (!xhr.responseText) { throw new Error('No response body.'); } @@ -790,10 +793,15 @@ const requestCallback = function( return function(err, response, body) { if (err) { - // browser-request just throws normal Error objects, - // not `TypeError`s like fetch does. So just assume any - // error is due to the connection. - err = new ConnectionError("request failed", err); + // the unit tests use matrix-mock-request, which throw the string "aborted" when aborting a request. + // See https://github.com/matrix-org/matrix-mock-request/blob/3276d0263a561b5b8326b47bae720578a2c7473a/src/index.js#L48 + const aborted = err.name === "AbortError" || err === "aborted"; + if (!aborted && !(err instanceof MatrixError)) { + // browser-request just throws normal Error objects, + // not `TypeError`s like fetch does. So just assume any + // error is due to the connection. + err = new ConnectionError("request failed", err); + } } if (!err) { try { @@ -930,3 +938,13 @@ export class ConnectionError extends Error { return this._cause; } } + +export class AbortError extends Error { + constructor() { + super("Operation aborted"); + } + + get name() { + return "AbortError"; + } +}