Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTPError code set to 'HTTPError' #1711 #1739

Merged
merged 5 commits into from Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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