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

response.writeHead() results in stalled response #83

Open
vocafeuvre opened this issue May 7, 2024 · 0 comments
Open

response.writeHead() results in stalled response #83

vocafeuvre opened this issue May 7, 2024 · 0 comments

Comments

@vocafeuvre
Copy link

Package version

@adonisjs/http-server@7.2.2

Describe the bug

Calling response.writeHead() when using response.stream() prevents the stream from being piped to the response body.

Cause of the issue

In line 1113 of file src/response.ts, a check against response.isPending is made before the stream is about to be piped to the body in response.streamBody(); if response.isPending is false, the finish() method returns and never reaches response.streamBody().

If response.writeHead() is called anywhere before a response.finish call (implicit or explicit), it will cause response.headersSent to be true, and since response.isPending = !response.headersSent && !response.finished, response.isPending will be false.

Why this is a bug

In my real-world app, I have to stream out a CSV file without knowing its length beforehand, and hence I cannot set the Content-Length header. This means, I have to set the Transfer-Encoding: chunked header, and write the response headers as soon as possible. This bug prevents me from doing that without resorting to a workaround.

My workaround is to force the piping of the stream to the response body by copying the contents of response.streamBody() and placing them in my controller function. Thankfully, the AdonisJS Response object exposes the underlying Node.js ServerResponse object, which makes the forcing of the pipe possible.

Reproduction

I created a reproduction using the starter web kit. In it, I have a web page at / endpoint, which contains two buttons Errored Dump and Dump. Errored Dump calls the /dump-error endpoint, which reproduces the bug. Dump calls the /dump endpoint, which shows my workaround as working.

Fix Proposal

The simplest way to fix this would be to add a response.writeHeadCalled flag, which will cancel out response.headersSent like this: response.isPending = !(response.writeHeadCalled ? false : response.headersSent) && !response.finished.

Reproduction repo

https://github.com/vocafeuvre/write-head-issue-repro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant