From 83c254947e1643b21bdddc97f984ba5600ad8a50 Mon Sep 17 00:00:00 2001 From: Tanguy Krotoff Date: Wed, 27 Jan 2021 18:31:12 +0100 Subject: [PATCH] Add support for Response.error() --- @types/index.d.ts | 5 +++++ README.md | 10 +++++++--- src/response.js | 18 +++++++++++++++++- test/response.js | 11 +++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/@types/index.d.ts b/@types/index.d.ts index b4d16ec9a..1f78ab25c 100644 --- a/@types/index.d.ts +++ b/@types/index.d.ts @@ -142,6 +142,8 @@ declare class Request extends Body { clone(): Request; } +type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect" + declare class Response extends Body { constructor(body?: BodyInit | null, init?: ResponseInit); @@ -150,8 +152,11 @@ declare class Response extends Body { readonly redirected: boolean; readonly status: number; readonly statusText: string; + readonly type: ResponseType; readonly url: string; clone(): Response; + + static error(): Response; } declare class FetchError extends Error { diff --git a/README.md b/README.md index 3e1d8d35e..0d65a953a 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ - [new Response([body[, options]])](#new-responsebody-options) - [response.ok](#responseok) - [response.redirected](#responseredirected) + - [response.type](#responsetype) - [Class: Headers](#class-headers) - [new Headers([init])](#new-headersinit) - [Interface: Body](#interface-body) @@ -587,9 +588,6 @@ An HTTP(S) response. This class implements the [Body](#iface-body) interface. The following properties are not implemented in node-fetch at this moment: -- `Response.error()` -- `Response.redirect()` -- `type` - `trailer` #### new Response([body[, options]]) @@ -615,6 +613,12 @@ Convenience property representing if the request ended normally. Will evaluate t Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0. +#### response.type + +_(deviation from spec)_ + +Convenience property representing the response's type. node-fetch only supports `'default'` and `'error'` and does not make use of [filtered responses](https://fetch.spec.whatwg.org/#concept-filtered-response). + ### Class: Headers diff --git a/src/response.js b/src/response.js index 3c69d5e9d..faebf1a18 100644 --- a/src/response.js +++ b/src/response.js @@ -21,7 +21,10 @@ export default class Response extends Body { constructor(body = null, options = {}) { super(body, options); - const status = options.status || 200; + // TODO Replace with nullish coalescing operator (??) when support for Node.js < 14 is dropped + // eslint-disable-next-line no-eq-null, eqeqeq, no-negated-condition + const status = options.status != null ? options.status : 200; + const headers = new Headers(options.headers); if (body !== null && !headers.has('Content-Type')) { @@ -32,6 +35,7 @@ export default class Response extends Body { } this[INTERNALS] = { + type: 'default', url: options.url, status, statusText: options.statusText || '', @@ -41,6 +45,10 @@ export default class Response extends Body { }; } + get type() { + return this[INTERNALS].type; + } + get url() { return this[INTERNALS].url || ''; } @@ -79,6 +87,7 @@ export default class Response extends Body { */ clone() { return new Response(clone(this, this.highWaterMark), { + type: this.type, url: this.url, status: this.status, statusText: this.statusText, @@ -107,12 +116,19 @@ export default class Response extends Body { }); } + static error() { + const response = new Response(null, {status: 0, statusText: ''}); + response[INTERNALS].type = 'error'; + return response; + } + get [Symbol.toStringTag]() { return 'Response'; } } Object.defineProperties(Response.prototype, { + type: {enumerable: true}, url: {enumerable: true}, status: {enumerable: true}, ok: {enumerable: true}, diff --git a/test/response.js b/test/response.js index f02b67f4d..8de19d626 100644 --- a/test/response.js +++ b/test/response.js @@ -35,6 +35,7 @@ describe('Response', () => { 'blob', 'json', 'text', + 'type', 'url', 'status', 'ok', @@ -49,6 +50,7 @@ describe('Response', () => { for (const toCheck of [ 'body', 'bodyUsed', + 'type', 'url', 'status', 'ok', @@ -125,6 +127,7 @@ describe('Response', () => { }); const cl = res.clone(); expect(cl.headers.get('a')).to.equal('1'); + expect(cl.type).to.equal('default'); expect(cl.url).to.equal(base); expect(cl.status).to.equal(346); expect(cl.statusText).to.equal('production'); @@ -205,4 +208,12 @@ describe('Response', () => { const res = new Response(); expect(res.url).to.equal(''); }); + + it('should support error() static method', () => { + const res = Response.error(); + expect(res).to.be.an.instanceof(Response); + expect(res.type).to.equal('error'); + expect(res.status).to.equal(0); + expect(res.statusText).to.equal(''); + }); });