Skip to content

Commit

Permalink
feat(node-fetch#1685): Add validation for status range and null body …
Browse files Browse the repository at this point in the history
…status in Response constructor
  • Loading branch information
Abhishek Singh committed Jan 25, 2023
1 parent 71e376b commit 3ce0633
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 7 deletions.
1 change: 0 additions & 1 deletion @types/index.test-d.ts
Expand Up @@ -37,7 +37,6 @@ async function run() {
// Post
try {
const request = new Request('http://byjka.com/buka');
new Request(new URL('http://byjka.com/buka'));
expectType<string>(request.url);
expectType<Headers>(request.headers);

Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -17,7 +17,8 @@
"test": "mocha",
"coverage": "c8 report --reporter=text-lcov | coveralls",
"test-types": "tsd",
"lint": "xo"
"lint": "xo",
"fix:lint": "xo --fix"
},
"repository": {
"type": "git",
Expand Down
31 changes: 27 additions & 4 deletions src/response.js
Expand Up @@ -10,6 +10,22 @@ import {isRedirect} from './utils/is-redirect.js';

const INTERNALS = Symbol('Response internals');

/**
* Checks the provided 'status' property to the Response constructor
* @param {*} status
* @throws RangeError if the status variable is not in the acceptable range of [200, 599]
* @returns The provided status value if it is valid
*/
function validateStatusValue(status) {
const statusValue = Number.parseInt(status, 10);

if (Number.isNaN(statusValue) || statusValue < 200 || statusValue > 599) {
throw new RangeError(`Failed to construct 'Response': The status provided (${status}) is outside the range [200, 599].`);
}

return statusValue;
};

/**
* Response class
*
Expand All @@ -23,12 +39,18 @@ export default class Response extends Body {
constructor(body = null, options = {}) {
super(body, options);

// eslint-disable-next-line no-eq-null, eqeqeq, no-negated-condition
const status = options.status != null ? options.status : 200;
// if status is not provided or is null, let's use default 200 value
// otherwise, lets check if the value is in correct range
const status = (typeof options.status === 'undefined' || options.status === null) ? 200 :
validateStatusValue(options.status);

const headers = new Headers(options.headers);

if (body !== null && !headers.has('Content-Type')) {
if (status === 204 && typeof body !== 'undefined' && body !== null) {
throw new TypeError("Failed to construct 'Response': Response with null body status cannot have body")
}

if (body !== null && !headers.has('Content-Type')) {
const contentType = extractContentType(body, this);
if (contentType) {
headers.append('Content-Type', contentType);
Expand Down Expand Up @@ -119,7 +141,8 @@ export default class Response extends Body {
}

static error() {
const response = new Response(null, {status: 0, statusText: ''});
// default error status code = 400
const response = new Response(null, {status: 400, statusText: ''});
response[INTERNALS].type = 'error';
return response;
}
Expand Down
22 changes: 21 additions & 1 deletion test/response.js
Expand Up @@ -248,11 +248,31 @@ describe('Response', () => {
expect(await res.text()).to.equal('a');
});

it('should throw a RangeError when options.status in the constructor is value outside of the range [200, 599]', async () => {
const inputStatus = 0
try {
new Response('a', { status: inputStatus })
} catch (err) {
expect(err).to.be.instanceOf(RangeError)
expect(err.message).to.equal(`Failed to construct 'Response': The status provided (${inputStatus}) is outside the range [200, 599].`)
}
})

it('should throw a TypeError when when a non-null body is provided with a null body status', async () => {
const inputStatus = 204
try {
new Response('a', { status: inputStatus })
} catch (err) {
expect(err).to.be.instanceOf(TypeError)
expect(err.message).to.equal("Failed to construct 'Response': Response with null body status cannot have body")
}
})

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.status).to.equal(400);
expect(res.statusText).to.equal('');
});

Expand Down

0 comments on commit 3ce0633

Please sign in to comment.