Skip to content

Commit

Permalink
HTTPError code set to 'HTTPError' #1711 (#1739)
Browse files Browse the repository at this point in the history
  • Loading branch information
Drewfergusson committed Jun 17, 2021
1 parent f896aa5 commit 0e167b8
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 38 deletions.
21 changes: 11 additions & 10 deletions readme.md
Expand Up @@ -1705,43 +1705,44 @@ Additionaly, the errors may have `request` (Got Stream) and `response` (Got Resp
#### got.RequestError
When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`. All the errors below inherit this one.
When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`. If there is no specific code supplied, `code` defaults to `ERR_GOT_REQUEST_ERROR`. All the errors below inherit this one.
#### got.CacheError
When a cache method fails, for example, if the database goes down or there's a filesystem error.
When a cache method fails, for example, if the database goes down or there's a filesystem error. Contains a `code` property with `ERR_CACHE_ACCESS` or a more specific failure code.
#### got.ReadError
When reading from response stream fails.
When reading from response stream fails. Contains a `code` property with `ERR_READING_RESPONSE_STREAM` or a more specific failure code.
#### got.ParseError
When server response code is 2xx, and parsing body fails. Includes a `response` property.
When server response code is 2xx, and parsing body fails. Includes a `response` property. Contains a `code` property with `ERR_BODY_PARSE_FAILURE` or a more specific failure code.
#### got.UploadError
When the request body is a stream and an error occurs while reading from that stream.
When the request body is a stream and an error occurs while reading from that stream. Contains a `code` property with `ERR_UPLOAD` or a more specific failure code.
#### got.HTTPError
When the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. Includes a `response` property.
When the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. Includes a `response` property. Contains a `code` property with `ERR_NON_2XX_3XX_RESPONSE` or a more specific failure code.
#### got.MaxRedirectsError
When the server redirects you more than ten times. Includes a `response` property.
When the server redirects you more than ten times. Includes a `response` property. Contains a `code` property with `ERR_TOO_MANY_REDIRECTS`.
#### got.UnsupportedProtocolError
When given an unsupported protocol.
When given an unsupported protocol. Contains a `code` property with `ERR_UNSUPPORTED_PROTOCOL`.
#### got.TimeoutError
When the request is aborted due to a [timeout](#timeout). Includes an `event` and `timings` property.
When the request is aborted due to a [timeout](#timeout). Includes an `event` and `timings` property. Contains a `code` property with `ETIMEDOUT`.
#### got.CancelError
When the request is aborted with `.cancel()`.
When the request is aborted with `.cancel()`. Contains a `code` property with `ERR_CANCELED`.
## Aborting the request
Expand Down
2 changes: 2 additions & 0 deletions source/as-promise/types.ts
Expand Up @@ -267,6 +267,7 @@ export class ParseError extends RequestError {

super(`${error.message} in "${options.url.toString()}"`, error, response.request);
this.name = 'ParseError';
this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_BODY_PARSE_FAILURE' : this.code;
}
}

Expand All @@ -279,6 +280,7 @@ export class CancelError extends RequestError {
constructor(request: Request) {
super('Promise was canceled', {}, request);
this.name = 'CancelError';
this.code = 'ERR_CANCELED';
}

get isCanceled() {
Expand Down
10 changes: 8 additions & 2 deletions source/core/index.ts
Expand Up @@ -1179,7 +1179,7 @@ An error to be thrown when a request fails.
Contains a `code` property with error class code, like `ECONNREFUSED`.
*/
export class RequestError extends Error {
code?: string;
code: string;
stack!: string;
declare readonly options: NormalizedOptions;
readonly response?: Response;
Expand All @@ -1191,7 +1191,7 @@ export class RequestError extends Error {
Error.captureStackTrace(this, this.constructor);

this.name = 'RequestError';
this.code = error.code;
this.code = error.code ?? 'ERR_GOT_REQUEST_ERROR';

if (self instanceof Request) {
Object.defineProperty(this, 'request', {
Expand Down Expand Up @@ -1249,6 +1249,7 @@ export class MaxRedirectsError extends RequestError {
constructor(request: Request) {
super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request);
this.name = 'MaxRedirectsError';
this.code = 'ERR_TOO_MANY_REDIRECTS';
}
}

Expand All @@ -1264,6 +1265,7 @@ export class HTTPError extends RequestError {
constructor(response: Response) {
super(`Response code ${response.statusCode} (${response.statusMessage!})`, {}, response.request);
this.name = 'HTTPError';
this.code = 'ERR_NON_2XX_3XX_RESPONSE';
}
}
/**
Expand All @@ -1276,6 +1278,7 @@ export class CacheError extends RequestError {
constructor(error: Error, request: Request) {
super(error.message, error, request);
this.name = 'CacheError';
this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_CACHE_ACCESS' : this.code;
}
}

Expand All @@ -1288,6 +1291,7 @@ export class UploadError extends RequestError {
constructor(error: Error, request: Request) {
super(error.message, error, request);
this.name = 'UploadError';
this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_UPLOAD' : this.code;
}
}

Expand Down Expand Up @@ -1319,6 +1323,7 @@ export class ReadError extends RequestError {
constructor(error: Error, request: Request) {
super(error.message, error, request);
this.name = 'ReadError';
this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_READING_RESPONSE_STREAM' : this.code;
}
}

Expand All @@ -1329,6 +1334,7 @@ export class UnsupportedProtocolError extends RequestError {
constructor(options: NormalizedOptions) {
super(`Unsupported protocol "${options.url.protocol}"`, {}, options);
this.name = 'UnsupportedProtocolError';
this.code = 'ERR_UNSUPPORTED_PROTOCOL';
}
}

Expand Down
26 changes: 14 additions & 12 deletions source/types.ts
Expand Up @@ -262,58 +262,60 @@ export interface Got extends Record<HTTPAlias, GotRequestFunction>, GotRequestFu
defaults: InstanceDefaults;

/**
An error to be thrown when a cache method fails.
For example, if the database goes down or there's a filesystem error.
An error to be thrown when a cache method fails. For example, if the database goes down or there's a filesystem error.
Contains a `code` property with `ERR_CACHE_ACCESS` or a more specific failure code.
*/
CacheError: typeof CacheError;

/**
An error to be thrown when a request fails.
Contains a `code` property with error class code, like `ECONNREFUSED`.
An error to be thrown when a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`.
If there is no specific code supplied, `code` defaults to `ERR_GOT_REQUEST_ERROR`.
*/
RequestError: typeof RequestError;

/**
An error to be thrown when reading from response stream fails.
An error to be thrown when reading from response stream fails. Contains a `code` property with
`ERR_READING_RESPONSE_STREAM` or a more specific failure code.
*/
ReadError: typeof ReadError;

/**
An error to be thrown when server response code is 2xx, and parsing body fails.
Includes a `response` property.
An error to be thrown when server response code is 2xx, and parsing body fails. Includes a
`response` property. Contains a `code` property with `ERR_BODY_PARSE_FAILURE` or a more specific failure code.
*/
ParseError: typeof ParseError;

/**
An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304.
Includes a `response` property.
Includes a `response` property. Contains a `code` property with `ERR_NON_2XX_3XX_RESPONSE` or a more specific failure code.
*/
HTTPError: typeof HTTPError;

/**
An error to be thrown when the server redirects you more than ten times.
Includes a `response` property.
Includes a `response` property. Contains a `code` property with `ERR_TOO_MANY_REDIRECTS`.
*/
MaxRedirectsError: typeof MaxRedirectsError;

/**
An error to be thrown when given an unsupported protocol.
An error to be thrown when given an unsupported protocol. Contains a `code` property with `ERR_UNSUPPORTED_PROTOCOL`.
*/
UnsupportedProtocolError: typeof UnsupportedProtocolError;

/**
An error to be thrown when the request is aborted due to a timeout.
Includes an `event` and `timings` property.
Includes an `event` and `timings` property. Contains a `code` property with `ETIMEDOUT`.
*/
TimeoutError: typeof TimeoutError;

/**
An error to be thrown when the request body is a stream and an error occurs while reading from that stream.
Contains a `code` property with `ERR_UPLOAD` or a more specific failure code.
*/
UploadError: typeof UploadError;

/**
An error to be thrown when the request is aborted with `.cancel()`.
An error to be thrown when the request is aborted with `.cancel()`. Contains a `code` property with `ERR_CANCELED`.
*/
CancelError: typeof CancelError;

Expand Down
5 changes: 4 additions & 1 deletion test/cache.ts
Expand Up @@ -120,7 +120,10 @@ test('cache error throws `got.CacheError`', withServer, async (t, server, got) =
const cache = {};

// @ts-expect-error Error tests
await t.throwsAsync(got({cache}), {instanceOf: got.CacheError});
await t.throwsAsync(got({cache}), {
instanceOf: got.CacheError,
code: 'ERR_CACHE_ACCESS'
});
});

test('doesn\'t cache response when received HTTP error', withServer, async (t, server, got) => {
Expand Down
35 changes: 28 additions & 7 deletions test/cancel.ts
Expand Up @@ -79,7 +79,10 @@ test.serial('does not retry after cancelation', withServerAndFakeTimers, async (
gotPromise.cancel();
});

await t.throwsAsync(gotPromise, {instanceOf: CancelError});
await t.throwsAsync(gotPromise, {
instanceOf: CancelError,
code: 'ERR_CANCELED'
});
await t.notThrowsAsync(promise, 'Request finished instead of aborting.');
});

Expand All @@ -102,7 +105,10 @@ test.serial('cleans up request timeouts', withServer, async (t, server, got) =>
}
});

await t.throwsAsync(gotPromise, {instanceOf: CancelError});
await t.throwsAsync(gotPromise, {
instanceOf: CancelError,
code: 'ERR_CANCELED'
});

// Wait for unhandled errors
await delay(40);
Expand All @@ -124,7 +130,10 @@ test.serial('cancels in-progress request', withServerAndFakeTimers, async (t, se
body.push(null);
});

await t.throwsAsync(gotPromise, {instanceOf: CancelError});
await t.throwsAsync(gotPromise, {
instanceOf: CancelError,
code: 'ERR_CANCELED'
});
await t.notThrowsAsync(promise, 'Request finished instead of aborting.');
});

Expand All @@ -144,7 +153,10 @@ test.serial('cancels in-progress request with timeout', withServerAndFakeTimers,
body.push(null);
});

await t.throwsAsync(gotPromise, {instanceOf: CancelError});
await t.throwsAsync(gotPromise, {
instanceOf: CancelError,
code: 'ERR_CANCELED'
});
await t.notThrowsAsync(promise, 'Request finished instead of aborting.');
});

Expand Down Expand Up @@ -220,7 +232,10 @@ test.serial('throws on incomplete (canceled) response - promise #2', withServerA
promise.cancel();
});

await t.throwsAsync(promise, {instanceOf: got.CancelError});
await t.throwsAsync(promise, {
instanceOf: got.CancelError,
code: 'ERR_CANCELED'
});
});

test.serial('throws on incomplete (canceled) response - stream', withServerAndFakeTimers, async (t, server, got, clock) => {
Expand Down Expand Up @@ -250,7 +265,10 @@ test('throws when canceling cached request', withServer, async (t, server, got)
promise.cancel();
});

await t.throwsAsync(promise, {instanceOf: got.CancelError});
await t.throwsAsync(promise, {
instanceOf: got.CancelError,
code: 'ERR_CANCELED'
});
});

test('throws when canceling cached request #2', withServer, async (t, server, got) => {
Expand All @@ -265,5 +283,8 @@ test('throws when canceling cached request #2', withServer, async (t, server, go
const promise = got({cache});
promise.cancel();

await t.throwsAsync(promise, {instanceOf: got.CancelError});
await t.throwsAsync(promise, {
instanceOf: got.CancelError,
code: 'ERR_CANCELED'
});
});
7 changes: 5 additions & 2 deletions test/error.ts
Expand Up @@ -28,7 +28,7 @@ test('properties', withServer, async (t, server, got) => {
// Class fields will always be initialized, even though they are undefined
// A test to check for undefined is in place below
// t.false({}.hasOwnProperty.call(error, 'code'));
t.is(error.code, undefined);
t.is(error.code, 'ERR_NON_2XX_3XX_RESPONSE');
t.is(error.message, 'Response code 404 (Not Found)');
t.deepEqual(error.options.url, url);
t.is(error.response.headers.connection, 'close');
Expand All @@ -41,6 +41,7 @@ test('catches dns errors', async t => {
t.regex(error.message, /ENOTFOUND|EAI_AGAIN/);
t.is(error.options.url.host, 'doesntexist');
t.is(error.options.method, 'GET');
t.is(error.code, 'ENOTFOUND');
});

test('`options.body` form error message', async t => {
Expand Down Expand Up @@ -130,6 +131,7 @@ test('`http.request` error', async t => {
}
}), {
instanceOf: got.RequestError,
code: 'ERR_GOT_REQUEST_ERROR',
message: 'The header content contains invalid characters'
});
});
Expand Down Expand Up @@ -215,7 +217,8 @@ test('promise does not hang on timeout on HTTP error', withServer, async (t, ser
await t.throwsAsync(got({
timeout: 100
}), {
instanceOf: TimeoutError
instanceOf: TimeoutError,
code: 'ETIMEDOUT'
});
});

Expand Down
2 changes: 2 additions & 0 deletions test/http.ts
Expand Up @@ -92,6 +92,7 @@ test('doesn\'t throw if `options.throwHttpErrors` is false', withServer, async (
test('invalid protocol throws', async t => {
await t.throwsAsync(got('c:/nope.com').json(), {
instanceOf: UnsupportedProtocolError,
code: 'ERR_UNSUPPORTED_PROTOCOL',
message: 'Unsupported protocol "c:"'
});
});
Expand Down Expand Up @@ -225,6 +226,7 @@ test('throws an error if the server aborted the request', withServer, async (t,
});

const error = await t.throwsAsync<ReadError>(got(''), {
code: 'ECONNRESET',
message: 'The server aborted pending request'
});

Expand Down
1 change: 1 addition & 0 deletions test/post.ts
Expand Up @@ -354,6 +354,7 @@ test('throws on upload error', withServer, async (t, server, got) => {
}
})), {
instanceOf: UploadError,
code: 'ERR_UPLOAD',
message
});
});
10 changes: 8 additions & 2 deletions test/promise.ts
Expand Up @@ -71,8 +71,14 @@ test('promise.json() can be called before a file stream body is open', withServe

const promise = got({body});
const checks = [
t.throwsAsync(promise, {instanceOf: CancelError}),
t.throwsAsync(promise.json(), {instanceOf: CancelError})
t.throwsAsync(promise, {
instanceOf: CancelError,
code: 'ERR_CANCELED'
}),
t.throwsAsync(promise.json(), {
instanceOf: CancelError,
code: 'ERR_CANCELED'
})
];

promise.cancel();
Expand Down

0 comments on commit 0e167b8

Please sign in to comment.