diff --git a/README.md b/README.md index 2a115e51d..64de8c0c7 100644 --- a/README.md +++ b/README.md @@ -419,6 +419,8 @@ If an error occurs, the promise is rejected with an `error` object containing 3 - `error.request` The request options such as `method`, `url` and `data` - `error.response` The http response object with `url`, `headers`, and `data` +If the error is due to an `AbortSignal` being used, the resulting `AbortError` is bubbled up to the caller. + ## `request.defaults()` Override or set default options. Example: diff --git a/src/fetch-wrapper.ts b/src/fetch-wrapper.ts index 36f6e4065..7325a6ee3 100644 --- a/src/fetch-wrapper.ts +++ b/src/fetch-wrapper.ts @@ -127,6 +127,7 @@ export default function fetchWrapper( }) .catch((error) => { if (error instanceof RequestError) throw error; + else if (error.name === "AbortError") throw error; throw new RequestError(error.message, 500, { request: requestOptions, diff --git a/test/request.test.ts b/test/request.test.ts index 0dea4ec41..817257572 100644 --- a/test/request.test.ts +++ b/test/request.test.ts @@ -1011,4 +1011,51 @@ x//0u+zd/R/QRUzLOw4N72/Hu+UG6MNt5iDZFCtapRaKt6OvSBwy8w== expect(mock.done()).toBe(true); }); }); + + it("bubbles up AbortError if the request is aborted", () => { + // AbortSignal and AbortController do not exist on + // Node < 15. The main parts of their API have been + // reproduced in the mocks below. + class AbortSignal { + abort = () => { + const e = new Error(""); + e.name = "AbortError"; + throw e; + }; + + addEventListener = () => {}; + } + + class AbortController { + abort = () => { + this.signal.abort(); + }; + signal = new AbortSignal(); + } + const abortController = new AbortController(); + const mock = fetchMock.sandbox().post( + "https://api.github.com/repos/octokit-fixture-org/release-assets/releases/tags/v1.0.0", + new Promise(() => { + abortController.abort(); + }) + ); + + return request("POST /repos/{owner}/{repo}/releases/tags/{tag}", { + owner: "octokit-fixture-org", + repo: "release-assets", + tag: "v1.0.0", + request: { + fetch: mock, + signal: abortController.signal, + }, + headers: { + "content-type": "text/plain", + }, + data: stringToArrayBuffer("Hello, world!\n"), + name: "test-upload.txt", + label: "test", + }).catch((error) => { + expect(error.name).toEqual("AbortError"); + }); + }); });