Preserve the original error name instead of returning raw AbortError (#57550) (#58842)

* Preserve the original error name instead of returning raw AbortError

* use Error as the default error name
This commit is contained in:
Pierre Gayvallet 2020-02-28 10:49:57 +01:00 committed by GitHub
parent 50f15a2357
commit 1e6977ffbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 31 deletions

View file

@ -1,23 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md)
## IHttpFetchError interface
<b>Signature:</b>
```typescript
export interface IHttpFetchError extends Error
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [body](./kibana-plugin-public.ihttpfetcherror.body.md) | <code>any</code> | |
| [req](./kibana-plugin-public.ihttpfetcherror.req.md) | <code>Request</code> | |
| [request](./kibana-plugin-public.ihttpfetcherror.request.md) | <code>Request</code> | |
| [res](./kibana-plugin-public.ihttpfetcherror.res.md) | <code>Response</code> | |
| [response](./kibana-plugin-public.ihttpfetcherror.response.md) | <code>Response</code> | |
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md)
## IHttpFetchError interface
<b>Signature:</b>
```typescript
export interface IHttpFetchError extends Error
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [body](./kibana-plugin-public.ihttpfetcherror.body.md) | <code>any</code> | |
| [name](./kibana-plugin-public.ihttpfetcherror.name.md) | <code>string</code> | |
| [req](./kibana-plugin-public.ihttpfetcherror.req.md) | <code>Request</code> | |
| [request](./kibana-plugin-public.ihttpfetcherror.request.md) | <code>Request</code> | |
| [res](./kibana-plugin-public.ihttpfetcherror.res.md) | <code>Response</code> | |
| [response](./kibana-plugin-public.ihttpfetcherror.response.md) | <code>Response</code> | |

View file

@ -37,6 +37,7 @@ describe('Fetch', () => {
});
afterEach(() => {
fetchMock.restore();
fetchInstance.removeAllInterceptors();
});
describe('http requests', () => {
@ -148,6 +149,42 @@ describe('Fetch', () => {
});
});
it('preserves the name of the original error', async () => {
expect.assertions(1);
const abortError = new DOMException('The operation was aborted.', 'AbortError');
fetchMock.get('*', Promise.reject(abortError));
await fetchInstance.fetch('/my/path').catch(e => {
expect(e.name).toEqual('AbortError');
});
});
it('exposes the request to the interceptors in case of aborted request', async () => {
const responseErrorSpy = jest.fn();
const abortError = new DOMException('The operation was aborted.', 'AbortError');
fetchMock.get('*', Promise.reject(abortError));
fetchInstance.intercept({
responseError: responseErrorSpy,
});
await expect(fetchInstance.fetch('/my/path')).rejects.toThrow();
expect(responseErrorSpy).toHaveBeenCalledTimes(1);
const interceptedResponse = responseErrorSpy.mock.calls[0][0];
expect(interceptedResponse.request).toEqual(
expect.objectContaining({
method: 'GET',
url: 'http://localhost/myBase/my/path',
})
);
expect(interceptedResponse.error.name).toEqual('AbortError');
});
it('should support get() helper', async () => {
fetchMock.get('*', {});
await fetchInstance.get('/my/path', { method: 'POST' });
@ -229,11 +266,6 @@ describe('Fetch', () => {
fetchMock.get('*', { foo: 'bar' });
});
afterEach(() => {
fetchMock.restore();
fetchInstance.removeAllInterceptors();
});
it('should make request and receive response', async () => {
fetchInstance.intercept({});

View file

@ -133,7 +133,7 @@ export class Fetch {
try {
response = await window.fetch(request);
} catch (err) {
throw new HttpFetchError(err.message, request);
throw new HttpFetchError(err.message, err.name ?? 'Error', request);
}
const contentType = response.headers.get('Content-Type') || '';
@ -153,11 +153,11 @@ export class Fetch {
}
}
} catch (err) {
throw new HttpFetchError(err.message, request, response, body);
throw new HttpFetchError(err.message, err.name ?? 'Error', request, response, body);
}
if (!response.ok) {
throw new HttpFetchError(response.statusText, request, response, body);
throw new HttpFetchError(response.statusText, 'Error', request, response, body);
}
return new HttpResponse({ request, response, body });

View file

@ -21,16 +21,19 @@ import { IHttpFetchError } from './types';
/** @internal */
export class HttpFetchError extends Error implements IHttpFetchError {
public readonly name: string;
public readonly req: Request;
public readonly res?: Response;
constructor(
message: string,
name: string,
public readonly request: Request,
public readonly response?: Response,
public readonly body?: any
) {
super(message);
this.name = name;
this.req = request;
this.res = response;

View file

@ -262,6 +262,7 @@ export interface IHttpResponseInterceptorOverrides<TResponseBody = any> {
/** @public */
export interface IHttpFetchError extends Error {
readonly name: string;
readonly request: Request;
readonly response?: Response;
/**

View file

@ -667,6 +667,8 @@ export type IContextProvider<THandler extends HandlerFunction<any>, TContextName
export interface IHttpFetchError extends Error {
// (undocumented)
readonly body?: any;
// (undocumented)
readonly name: string;
// @deprecated (undocumented)
readonly req: Request;
// (undocumented)