From c520ac62c8a49607a40992d4bd43081c86481a97 Mon Sep 17 00:00:00 2001 From: Dan Hensby Date: Thu, 15 Oct 2026 15:17:32 +0100 Subject: [PATCH 1/3] docs: remove non-existent `method` param from Response constructor JSDoc The Response constructor never accepted a `method` option; the param was copied from the Request constructor docs. Co-Authored-By: Claude Opus 5.5 --- docs/api/response.md | 5 ++--- lib/response.js | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/api/response.md b/docs/api/response.md index e0b04020..98b59512 100644 --- a/docs/api/response.md +++ b/docs/api/response.md @@ -8,21 +8,20 @@ response signature. **Kind**: global class * [Response](#Response) - * [new Response(headers, method, [body], ...otherOptions)](#new_Response_new) + * [new Response(headers, [body], ...otherOptions)](#new_Response_new) * [.get(field)](#Response+get) ⇒ string \| undefined * [.redirect(url)](#Response+redirect) * [.set(field, value)](#Response+set) -### new Response(headers, method, [body], ...otherOptions) +### new Response(headers, [body], ...otherOptions) Create a new Response instance. | Param | Type | Description | | --- | --- | --- | | headers | object | key-value object of headers | -| method | string | the HTTP method | | [body] | object | optional key-value object of body parameters | | ...otherOptions | object | any other properties that should be assigned to the request by your webserver | diff --git a/lib/response.js b/lib/response.js index 41a47136..833910f2 100644 --- a/lib/response.js +++ b/lib/response.js @@ -16,7 +16,6 @@ class Response { * Create a new Response instance. * @constructor * @param headers {object} key-value object of headers - * @param method {string} the HTTP method * @param body {object=} optional key-value object of body parameters * @param otherOptions {...object} any other properties that should be assigned to the request by your webserver */ From a4f3ff7ad8f1d8c2e65193a53a74a6907aa56df6 Mon Sep 17 00:00:00 2001 From: Dan Hensby Date: Thu, 15 Oct 2026 15:18:24 +0100 Subject: [PATCH 2/3] docs: document that the Response status is set by the handlers The Response constructor always starts the `status` at 200 and does not take a `status` option. The handlers own the status they send (200 for a token, the error's code on failure, 302 for a redirect), so a status passed in by the caller would at best be overwritten and at worst leak into a successful response. Say so in the constructor JSDoc, and note that `otherOptions` never overwrite properties the response already has, such as `status` or its methods. Also fix the `otherOptions` description, which referred to the request. Co-Authored-By: Claude Opus 5.5 --- docs/api/response.md | 5 ++++- lib/response.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/api/response.md b/docs/api/response.md index 98b59512..0608c423 100644 --- a/docs/api/response.md +++ b/docs/api/response.md @@ -18,12 +18,15 @@ response signature. ### new Response(headers, [body], ...otherOptions) Create a new Response instance. +The `status` always starts as `200` and is set by the handlers (for example +`302` for a redirect, or the error's code), so it cannot be passed in. + | Param | Type | Description | | --- | --- | --- | | headers | object | key-value object of headers | | [body] | object | optional key-value object of body parameters | -| ...otherOptions | object | any other properties that should be assigned to the request by your webserver | +| ...otherOptions | object | any other properties that should be assigned to the response by your webserver; properties the response already has (such as `status` or its methods) are not overwritten | **Example** ```js diff --git a/lib/response.js b/lib/response.js index 833910f2..cc494ea0 100644 --- a/lib/response.js +++ b/lib/response.js @@ -14,10 +14,13 @@ class Response { /** * Create a new Response instance. + * + * The `status` always starts as `200` and is set by the handlers (for example + * `302` for a redirect, or the error's code), so it cannot be passed in. * @constructor * @param headers {object} key-value object of headers * @param body {object=} optional key-value object of body parameters - * @param otherOptions {...object} any other properties that should be assigned to the request by your webserver + * @param otherOptions {...object} any other properties that should be assigned to the response by your webserver; properties the response already has (such as `status` or its methods) are not overwritten */ constructor({ headers = {}, body = {}, ...otherOptions } = {}) { this.status = 200; From c89d87f91c9a36d0f12f2d38e3587cc741bedbc8 Mon Sep 17 00:00:00 2001 From: Dan Hensby Date: Fri, 16 Oct 2026 10:51:34 +0100 Subject: [PATCH 3/3] test: pin that the Response status cannot be passed in Check that the Response constructor ignores a `status` option, and that a successful token response is 200 (RFC 6749 section 5.1) even when the caller creates the Response with another status. Co-Authored-By: Claude Opus 5.5 --- .../client-credential-workflow_test.js | 32 +++++++++++++++++++ test/integration/response_test.js | 6 ++++ 2 files changed, 38 insertions(+) diff --git a/test/compliance/client-credential-workflow_test.js b/test/compliance/client-credential-workflow_test.js index df5865f8..e15139a8 100644 --- a/test/compliance/client-credential-workflow_test.js +++ b/test/compliance/client-credential-workflow_test.js @@ -106,6 +106,38 @@ describe('ClientCredentials Workflow Compliance (4.4)', function () { db.refreshTokens.has(token.refreshToken).should.equal(false); }); + /** + * 5.1. Successful Response + * + * The authorization server issues an access token and optional + * refresh token, and constructs the response by adding the following + * parameters to the entity-body of the HTTP response with a 200 (OK) + * status code + */ + it('returns status 200 for a successful token response even if the initial status is 404', async function () { + const response = new Response({ status: 404 }); + const request = createRequest({ + body: { + grant_type: 'client_credentials', + scope: enabledScope, + }, + headers: { + authorization: 'Basic ' + Buffer.from(clientDoc.id + ':' + clientDoc.secret).toString('base64'), + 'content-type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + + const token = await oAuth2Server.token(request, response); + + response.body.access_token.should.equal(token.accessToken); + response.body.token_type.should.equal('Bearer'); + db.accessTokens.has(token.accessToken).should.equal(true); + + // RFC 6749 section 5.1 specifies status 200 for a successful token response. + response.status.should.equal(200); + }); + /** * 7. Accessing Protected Resources * diff --git a/test/integration/response_test.js b/test/integration/response_test.js index cbaf529f..589b1eea 100644 --- a/test/integration/response_test.js +++ b/test/integration/response_test.js @@ -32,6 +32,12 @@ describe('Response integration', function () { response.status.should.equal(200); }); + + it('should not set the `status` from the options', function () { + const response = new Response({ body: {}, headers: {}, status: 404 }); + + response.status.should.equal(200); + }); }); describe('get()', function () {