express icon indicating copy to clipboard operation
express copied to clipboard

Throw on invalid status codes

Open jonchurch opened this issue 4 years ago • 14 comments

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:

  • [x] 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
  • [x] 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: https://github.com/expressjs/discussions/issues/233

jonchurch avatar Mar 10 '20 02:03 jonchurch

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.

jonchurch avatar Mar 10 '20 03:03 jonchurch

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.

gireeshpunathil avatar Mar 10 '20 03:03 gireeshpunathil

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 :) !

dougwilson avatar Mar 10 '20 03:03 dougwilson

Fixed the tests. Now the CI fails on Node.js 0.10 because there is no Number.isInteger function available there.

Assuming we're dropping that version, then this should be good to go pending any requested changes.

jonchurch avatar Mar 10 '20 12:03 jonchurch

Fixed the tests. Now the CI fails on Node.js 0.10 because there is no Number.isInteger function available there.

Assuming we're dropping that version, then this should be good to go pending any requested changes.

A few of us thumbs upped that, but also wanted to call out that yes it is being dropped, so let 0.10 fail on this PR; 0.10 will be removed from the branch's CI prior to this change, so that version failing will turn to passing as things are merged.

dougwilson avatar Mar 10 '20 12:03 dougwilson

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?

gireeshpunathil avatar Mar 20 '20 06:03 gireeshpunathil

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

jonchurch avatar Apr 01 '20 20:04 jonchurch

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

Yes, as stated in https://github.com/expressjs/express/pull/4223#issuecomment-602102852 , 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.

dougwilson avatar Apr 01 '20 20:04 dougwilson

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 avatar Apr 01 '20 20:04 jonchurch

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

jonchurch avatar Apr 01 '20 20:04 jonchurch

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.

dougwilson avatar Apr 02 '20 02:04 dougwilson

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.

abenhamdine avatar Mar 10 '23 10:03 abenhamdine