Skip to content

docs: document that the Response status is set by the handlers - #510

Open
dhensby wants to merge 3 commits into
node-oauth:masterfrom
dhensby:fix/response-status-option
Open

dhensby wants to merge 3 commits into
node-oauth:masterfrom
dhensby:fix/response-status-option

Conversation

@dhensby

@dhensby dhensby commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

new Response({ status: 404 }) produces a response whose status is 200. This PR originally changed the constructor to honour status, but review showed why it shouldn't. Response isn't a general model of an HTTP response. It is the library's output: the handlers fill it in and the adapter copies it onto the real HTTP response. The handlers set the status themselves:

  • 200 for a token;
  • the error's code on failure;
  • 302 through redirect().

So a status passed in by the caller has no legitimate use. @jankapunkt showed it would leak into a successful token response, against RFC 6749 搂5.1.

The status has started at 200 since 2015, and that doesn't change here. This PR now documents that behaviour and pins it with tests, and makes no change to how the library behaves:

  • JSDoc: the Response constructor says the status always starts as 200 and is set by the handlers, so it can't be passed in. The otherOptions description now says it never overwrites properties the response already has, such as status or its methods; it also said "request" where it meant "response". A separate commit removes a method param, which the constructor never accepted. docs/api/response.md is regenerated.
  • Tests: a constructor test checks that status: 404 is ignored. @jankapunkt's compliance test checks that a successful token response is 200 even when the Response was created with status: 404.

index.d.ts is unchanged.

Linked issue(s)

None. Found while reviewing other open PRs.

Involved parts of the project

  • lib/response.js: constructor JSDoc only
  • docs/api/response.md: regenerated from JSDoc
  • test/integration/response_test.js, test/compliance/client-credential-workflow_test.js

Added tests?

Yes, as above. Both pass on master and fail if the constructor honours status. I checked that against the earlier version of this PR. biome check . is clean and the full mocha suite passes (466).

OAuth2 standard

No change in behaviour. The new compliance test pins RFC 6749 搂5.1's 200 (OK) for a successful token response.

Reproduction

const { Response } = require('@node-oauth/oauth2-server');
new Response({ status: 404 }).status; // 200, by design

馃 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

馃煛 Changes recommended

The constructor typings reject previously accepted array-valued headers.

0 open findings

What changed in this PR

Fixes Response construction to honour integer status values while retaining the default 200 for other values.

Changes:

  • Handles explicit status values and adds regression tests.
  • Expands constructor typings.
  • Updates constructor documentation and removes the incorrect method parameter.
File Description
test/鈥媔ntegration/鈥媟esponse_test.js Tests explicit status and function-valued status fallback.
lib/鈥媟esponse.js Accepts integer status values and updates JSDoc.
index.d.ts Declares constructor options explicitly.
docs/鈥媋pi/鈥媟esponse.md Updates generated constructor documentation.

馃 Review effort: Balanced


馃挕 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@dhensby
dhensby force-pushed the fix/response-status-option branch from 0020aac to a242162 Compare October 15, 2026 14:40
@dhensby
dhensby marked this pull request as ready for review October 15, 2026 14:40
@dhensby dhensby added this to the 5.4 milestone Oct 15, 2026
@dhensby
dhensby requested a balanced review from Copilot October 15, 2026 14:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

馃煝 Approval recommended

The focused change matches the intended behaviour, includes regression coverage, and has no identified blocking issues.

0 open findings

馃 Review effort: Balanced

@dhensby
dhensby requested a review from jankapunkt October 15, 2026 15:09
@jankapunkt

Copy link
Copy Markdown
Member

While this fixes the immediate visible issue, there is one indirect consequence of this: "OAuth2 Standard not affected" is a little too broad. If someone passes status 404, a successful token response will now keep that status, even though OAuth2 expects 200. The usual behavior stays the same when no status is passed.

Consider the following test case in client-credential-workflow_test.js:

    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);
    });

In its current state it will fail because TokenHandler.updateSuccessResponse still implies the previous behavior and does not set any 200 response.

@dhensby
dhensby marked this pull request as draft October 15, 2026 20:43
@dhensby dhensby changed the title fix: honour status option in Response constructor docs: document that the Response status is set by the handlers Oct 16, 2026
@dhensby

dhensby commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Thanks; that's a good point and something I had thought about. Initially I was thinking Request would be a fully abstract implementation of a HTTP response, but really it's an internal representation and there's no reason for a consumer to be constructing it with a status that needs persisting. I've reworked the PR just to improve the docs.

@dhensby
dhensby marked this pull request as ready for review October 16, 2026 09:56
@dhensby
dhensby force-pushed the fix/response-status-option branch from 2d019cf to 5cd587f Compare October 16, 2026 09:56
dhensby and others added 3 commits October 16, 2026 11:08
The Response constructor never accepted a `method` option; the param was
copied from the Request constructor docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
@dhensby
dhensby force-pushed the fix/response-status-option branch from 5cd587f to c89d87f Compare October 16, 2026 10:08

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants