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

Throw on invalid status codes #4212

Merged
merged 30 commits into from
Jul 30, 2024
Merged

Conversation

jonchurch
Copy link
Member

@jonchurch jonchurch commented Mar 10, 2020

Closes #3143

Will throw a RangeError if status code:

  • is less than 100
  • is greater than 999

This aligns with Node.js' behavior of throwing if given something outside that range

Will throw a TypeError if status code is:

  • Not an integer (string representation of integer included)

This is a choice we are making to limit the acceptable input.

Use res.status internally when setting status codes

the PR also ensures we use res.status internally when setting status codes, to allow us to use the validation logic internally.

Test changes

I cleaned up the tests to test acceptable range, and invalid codes, and removed the iojs logic as its not supported in v5.

TODO:

  • Update the PR description to be specific to the actual changes in this PR, possibly reopen the PR since direction has changed
    • Notably, this PR currently throws on strings, redefines the valid range of codes to between 1xx and 9xx, throws on non-integer floats (e.g. 500.5, but allows 500.00 bc it is the same to JS), throws a RangeError if we get a status code outside 1xx to 9xx range
  • Ensure the tests are accurate to these changes, and clean up the tests in here
  • Update the v5 docs to reflect said changes (separate PR to expressjs.com)

related: expressjs/discussions#233

test/res.status.js Outdated Show resolved Hide resolved
@dougwilson dougwilson added the pr label Mar 10, 2020
@jonchurch
Copy link
Member Author

I realized after opening this that Node.js does not throw on inputs like 500.5, this PR however does. From the other PR, I think we decided to throw on these cases, but I wanted to make clear that from my limited testing Node.js is not throwing on floats.

@gireeshpunathil
Copy link
Contributor

I wanted to make clear that from my limited testing Node.js is not throwing on floats.

@jonchurch - my assertion is that 500.5 is definitely invalid, so throwing is the right thing to do.

@dougwilson
Copy link
Contributor

Yea, I don't have any issues with this throwing on a float; we want to throw on whatever Node.js throws on as the minimum bar. If we can also help the users by also throwing on definitely nonsensical inputs (like status codes with fractions) that makes sense of course :) !

@jonchurch

This comment was marked as outdated.

lib/response.js Outdated Show resolved Hide resolved
@dougwilson

This comment was marked as outdated.

@gireeshpunathil
Copy link
Contributor

as per the TC discussion, this is ready to merge, who is going to do that? @dougwilson , I see your red-X on this - is that still valid, or you are going to remove it and land?

@jonchurch
Copy link
Member Author

jonchurch commented Apr 1, 2020

Thinking more about this and something bothers me. I took the approach the previous PR did, since it had been reviewed, but now I'm questioning the use of res.status internally to set statuses.

If someone monkey-patches res.status it will alter the internal behavior of setting status codes on responses. That's not different though for other functions used in response, like res.type for example.

My question has two parts:

  • Is it a breaking change to be relying on res.status() to set status codes internally?
  • Do we want to distinguish between private vs public methods? (there are only two things marked private in response according to jsdoc comments)

See an example of the change in the diff: https://github.com/expressjs/express/pull/4212/files#diff-d86a59ede7d999db4b7bc43cb25a1c11L137-R142

@dougwilson
Copy link
Contributor

Is it a breaking change to be relying on res.status() to set status codes internally?

Yes, as stated in #4223 (comment) , but this PR is already a breaking change, right? So I'm not sure if it's super relevant. The change itself makes sense to make, just like we call res.type internally and not directly get the content-type response header. Even getting headers we internally use req.get and not req.headers.

Do we want to distinguish between private vs public methods? (there are only two things marked private in response according to jsdoc comments)

I'm not really following on what this part of the question really is. The main reason the internals use Express' own API is especially useful for AOP type of design patterns, if the user so chooses to do them. The Node.js HTTP APIs do the same patterns as well, AFAIK.

@jonchurch
Copy link
Member Author

I wasn't clear. Re: breaking, I meant that someone's v4 res.status monkey patch might affect code in unexpected ways under v5, because it is used in more places than before.

You've answered my second question I believe. We aren't interested in making some methods private and off limits to users.

Thanks, I wanted to bring up this point (re: effects of monkey-patching res.status with these changes) just so someone else could check it.

Realizing that we use a lot of these helper methods internally would indicate that this change is not out of step with what is standard.

@jonchurch
Copy link
Member Author

Just read that linked comment and saw you did directly address the concern already 👍

@dougwilson
Copy link
Contributor

Yep! I did, though, not directly address the monkey patching messing something up; that is indeed the case, but I don't think any more so than other aspects of Node.js and Javascript. I think that it is going to be possible for users to override something and cause a breakage, but I'm not sure that the effort in order to prevent such a thing is really worth it. From support experience, I think it is extremely rare for such an issue to really show up, haha.

@abenhamdine
Copy link
Contributor

I think this PR should target branch https://github.com/expressjs/express/tree/5.0 and not master.
And if it's ok, it should be merged aswell in v5 branch.

@wesleytodd wesleytodd mentioned this pull request Mar 21, 2024
39 tasks
ctcpip
ctcpip previously requested changes Jun 5, 2024
History.md Outdated Show resolved Hide resolved
lib/response.js Show resolved Hide resolved
Co-authored-by: Chris de Almeida <ctcpip@users.noreply.github.com>
test/res.sendStatus.js Outdated Show resolved Hide resolved
@jonchurch jonchurch changed the base branch from 5.x to 5.0 July 27, 2024 18:19
@wesleytodd
Copy link
Member

I am landing this despite the pending 22 test and the coverage report. I think we agree it is good and if we have to fix CI we can do it along with dropping node 18. I am getting to the point where I think we should merge all these pending ones and live with 5.0 being broken until we land the node@18 change anyway.

@wesleytodd wesleytodd merged commit 723b545 into expressjs:5.0 Jul 30, 2024
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants