-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
Duplicated response.writeHead
calling is not checked in specific case
#20932
Comments
I also found that if you use different Though this doesn't work with Either only |
Full context available in #21289 and the referred link. In short:
Probably not, but given that there is an optimization to bypass header caching in the fast path, and given that calling |
I see. |
this has been documented with explanation to the behavior. Closing. |
@gireeshpunathil can you link me to the doc change itself, or at least an updated version of the documentation? |
@getify - sorry, I missed this question. the behavior difference between writeHead and setHeader w.r.t repeated header updates are documented here: https://nodejs.org/dist/latest-v13.x/docs/api/http.html#http_response_setheader_name_value hope this helps |
That documentation does not, IMO, spell out an explanation or warning about the case listed here. I've read it several times and I still find it lacking in clarity. Knowing this problem (from this issue), I can sorta infer that the bypass-caching-headers fast path optimization is the key to understanding this gotcha... but only barely. If I didn't know about this issue, it is not clear to me from reading the docs that you will get an error (on double call) only if you previously called setHeader. I still find that bizarre and the docs do not warn me about it. When docs say "don't call this twice", a reasonable person expects that violating that will give an error. If there are optimizations in place that prevent an error from being displayed, such that the second call silently fails, this is a gotcha. And the docs do not warn about that gotcha. |
@getify - thanks. I too read it many times now; and I admit something can be improved there, but not able to figure out how (I wrote those new sentences earlier) . Do you want to try phrasing something? |
As it is documented,
response.writeHead
method should be called only once.When the
response.writeHead
method is called twice, an error ("Can't set headers after they are sent.") is thrown ifresponse.setHeader
method was called. And the error is not thrown if theresponse.setHeader
method was not called.For example:
Run this code as a server:
And run this code as a client (using request module):
That works fine without an error but the code as server calls the
response.writeHead
method twice.So, run this code as a server instead:
And run the client above.
Then, an error "Can't set headers after they are sent." is thrown.
Just only the
response.setHeader
method was added to the second server.Is this correct behavior?
Of course the
response.writeHead
method should not be called again. However I feel strange about that it is checked only when theresponse.setHeader
method was called.It seems that this issue is relevant to #8446, maybe. I take notice of an error that is thrown by the
response.setHeader
method.In
OutgoingMessage.prototype.setHeader
, the error is thrown if the headers are already sent (rendered).node/lib/_http_outgoing.js
Line 471 in 9a02de7
In
ServerResponse.prototype.writeHead
, theOutgoingMessage.prototype.setHeader
is called only when current instance has header data (i.e. it hasthis[outHeadersKey]
).node/lib/_http_server.js
Line 224 in 9a02de7
In other words, the
response.setHeader
method that checks duplicated calling is called only when that method was already called (i.e.this[outHeadersKey]
was already set).Also, duplicated calling is checked after headers were merged.
node/lib/_http_server.js
Line 234 in 9a02de7
I think that the checking should be moved to after
if ... else
.That is, duplicated calling should be checked whether headers were merged or not.
Or, checking at top of
writeHead
is better because it has to do nothing when it throws an error.And also, it seems that there is another problem in that checking.
Run this code as a server instead:
This is the same as the code that throws an error except for last header name. However this does not throw an error.
After header were merged, duplicated calling is checked only when the last header name is
undefined
.node/lib/_http_server.js
Line 234 in 9a02de7
A value of the
k
was updated repeatedly, and it has last header name or initial value. And duplicated calling is checked by theresponse.setHeader
method in a loop only when thek
is truthy.If the
k === undefined
means that theresponse.setHeader
method never be called, that was not sufficient.I think that checking the
k
is not needed (i.e.if (this._header) {
) because duplicated calling can be checked even if that was already checked in theresponse.setHeader
method.This problem also is solved by changing above, as I indicated.
The text was updated successfully, but these errors were encountered: