-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
Error if message is bigger than Content-Length #39133
base: main
Are you sure you want to change the base?
Conversation
lib/_http_outgoing.js
Outdated
@@ -66,7 +66,8 @@ const { | |||
ERR_STREAM_ALREADY_FINISHED, | |||
ERR_STREAM_WRITE_AFTER_END, | |||
ERR_STREAM_NULL_VALUES, | |||
ERR_STREAM_DESTROYED | |||
ERR_STREAM_DESTROYED, | |||
ERR_CONTENT_LENGTH_HEADER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ERR_CONTENT_LENGTH_HEADER | |
ERR_CONTENT_LENGTH_MISMATCH, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Could this list also be sorted in alphabetical order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks for the feedback, would make the changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would also be nice if you check content length in .end() to make sure not to few bytes have been written as well.
Unrelated documentation changes in |
Hey @ronag for .end(), how many bytes would be a good amount so the error is not triggered? |
If it doesn’t match content length then error |
lib/_http_outgoing.js
Outdated
@@ -514,6 +517,9 @@ function processHeader(self, state, key, value, validate) { | |||
function storeHeader(self, state, key, value, validate) { | |||
if (validate) | |||
validateHeaderValue(key, value); | |||
if (key === 'Content-Length') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (key === 'Content-Length') { | |
if (key.toLowerCase() === 'content-length') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://nodejs.org/es/docs/guides/anatomy-of-an-http-transaction/
It's important to note here that all headers are represented in lower-case only, regardless of how the client actually sent them. This simplifies the task of parsing headers for whatever purpose.
@@ -575,6 +581,10 @@ OutgoingMessage.prototype.setHeader = function setHeader(name, value) { | |||
validateHeaderName(name); | |||
validateHeaderValue(name, value); | |||
|
|||
if (name === 'content-length') { | |||
this._contentLength = NumberParseInt(value); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Isn’t store header enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry, shouldn't be there, my mistake
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked the code again and store header is not enough, the Content-length is not set when setHeader is used... I think it happens because it never goes throw processHeader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting inside the validation function is wrong though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seemed right sorry, I'll create a new function for the validating the content length
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of unrelated doc changes...
@betochf Could you please rebase and resolve the merge conflicts? |
@RaisinTen done, it was an error in the Doc |
let headers = this[kOutHeaders]; | ||
if (headers === null) | ||
this[kOutHeaders] = headers = ObjectCreate(null); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. By the way, are changes in doc/api/errors.md
also required? It seems like most of them are unrelated to an issue as well.
@@ -756,6 +772,12 @@ function write_(msg, chunk, encoding, callback, fromEnd) { | |||
return false; | |||
} | |||
|
|||
if (msg._contentLength) { | |||
if (msg[kBytesWritten] > msg._contentLength) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can combine these two if statements
if (msg[kBytesWritten] > msg._contentLength) { | ||
throw new ERR_CONTENT_LENGTH_MISMATCH(msg._contentLength, msg[kBytesWritten]); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this check needed if you already have it below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs more tests.
@ronag I did the changes... which other tests should I try? |
I think 3 tests should be added at least:
|
@@ -81,7 +84,7 @@ const HIGH_WATER_MARK = getDefaultHighWaterMark(); | |||
const { CRLF } = common; | |||
|
|||
const kCorked = Symbol('corked'); | |||
|
|||
const kBytesWritten = Symbol ('bytes'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const kBytesWritten = Symbol ('bytes'); | |
const kBytesWritten = Symbol('bytes'); |
@@ -849,6 +871,11 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
this.socket.cork(); | |||
} | |||
|
|||
const byteCount = (this[kBytesWritten] + chunk.length); | |||
if (this._contentLength && (byteCount) !== this._contentLength) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (this._contentLength && (byteCount) !== this._contentLength) { | |
if (this._contentLength !== undefined && (byteCount) !== this._contentLength) { |
@@ -1191,6 +1199,10 @@ E('ERR_INVALID_CHAR', | |||
} | |||
return msg; | |||
}, TypeError); | |||
E('ERR_INVALID_CONTENT_LENGTH', function(size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ERR_INVALID_ARG_VALUE
could be used instead.
@@ -849,6 +871,11 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
this.socket.cork(); | |||
} | |||
|
|||
const byteCount = (this[kBytesWritten] + chunk.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may not be entirely accurate in every case due to content encoding. For instance, if I pass in w.end('afef', 'hex')
, I'm only writing 2 bytes. The calculation here needs to take into consideration the encoding
and the actual byte length.
let msg; | ||
if (byteCount < contentLength) { | ||
msg = 'less'; | ||
} else msg = 'more'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let msg; | |
if (byteCount < contentLength) { | |
msg = 'less'; | |
} else msg = 'more'; | |
const msg = byteCount < contentLength ? 'less' : 'more'; |
Pr for issue #39041
The test for the changes is very simple, it just contains a 200 request with a header specifying the "Content-Lenght", in this case with a size of 2 bytes, with a response of 4 so the error could be triggered.
tests: