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
refactor: update Reply module #4072
Conversation
* Use node.js 14 syntax * Improve code readability * Reuse Reply's methods where possible
lib/reply.js
Outdated
// it must be chunked for trailer to work | ||
reply.header('Transfer-Encoding', 'chunked') | ||
reply.header('Trailer', header.trim()) |
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 think we can completely delete filter
here (and also in sendTrailer()
) because it's already validated in Reply.prototype.trailer()
, but if we leave it, then we must also check it for invalid trailers (INVALID_TRAILERS
), wdyt?
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.
No, removeTrailer
will set the value to undefined
. It is required to check if the value is function.
INVALID_TRAILERS
is not the same case, as it never be able to set the invalid key-value
pair. There is no need to check it again.
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.
👌
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'm not fond of this massive changes in syntax. I would prefer if we hold off from doing these unless there are specific needs.
lib/reply.js
Outdated
// it must be chunked for trailer to work | ||
reply.header('Transfer-Encoding', 'chunked') | ||
reply.header('Trailer', header.trim()) | ||
reply.header('Trailer', Object.keys(reply[kReplyTrailers]).filter(trailer => typeof reply[kReplyTrailers][trailer] === 'function').join(' ')) |
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.
filter() is very slow.
lib/reply.js
Outdated
reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload) | ||
} else if (req.raw.method !== 'HEAD' && reply[kReplyHeaders]['content-length'] !== Buffer.byteLength(payload)) { | ||
reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload) | ||
if (!reply.hasHeader('content-length') || (req.raw.method !== 'HEAD' && parseInt(reply.getHeader('content-length'), 10) !== Buffer.byteLength(payload))) { |
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.
please use the fast-path for getHeader.
lib/reply.js
Outdated
} | ||
|
||
Reply.prototype.removeTrailer = function (key) { | ||
if (this[kReplyTrailers] === null) return this | ||
this[kReplyTrailers][key.toLowerCase()] = undefined | ||
if (this[kReplyTrailers] !== 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.
I think I add it as a early exit approach.
The readability didn't change a lot when here is few line of code.
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.
👌
lib/reply.js
Outdated
for (var i = 0; i !== keys.length; ++i) { | ||
const key = keys[i] | ||
this.header(key, headers[key]) | ||
for (const headerName in headers) { |
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.
There is a significant difference between Object.keys
and for...in
:
for...in
https://262.ecma-international.org/13.0/#sec-createforiniterator:
It is used to create a For-In Iterator object which iterates over the own and inherited enumerable string properties of object in a specific order.
Object.keys
https://262.ecma-international.org/13.0/#sec-object.keys:
- Let nameList be ? EnumerableOwnPropertyNames(obj, key).
In short, the Object.keys
implementation does not enumerate properties from higher up in the prototype chain. It only iterates the actual headers object properties.
lib/reply.js
Outdated
@@ -165,6 +165,7 @@ Reply.prototype.send = function (payload) { | |||
// If user doesn't set charset, we will set charset to utf-8 | |||
if (contentType.indexOf('charset') === -1) { | |||
const customContentType = contentType.trim() | |||
|
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.
What is happening here? Is this a line ending 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.
Nope, just a new line to separate var definition and if condition (I added it when I was refactoring this reverted block of code). Delete?
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.
Looks good to me.
CI is failing |
Looks like CI is passing after I merged in the main branch. |
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.
lgtm
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Hi, I refactored the Reply module a little bit.
Tests are passing, the benchmark result is the same as before.
Checklist
npm run test
andnpm run benchmark
and the Code of conduct