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

fix(ext/flash): Correctly handle errors for chunked responses #17303

Merged
merged 5 commits into from
Jan 14, 2023
Merged

fix(ext/flash): Correctly handle errors for chunked responses #17303

merged 5 commits into from
Jan 14, 2023

Conversation

kamilogorek
Copy link
Contributor

The leading cause of the problem was that handleResponse has tryRespondChunked passed as an argument, which in turn is implemented as a call to core.ops.op_try_flash_respond_chuncked, that throws in the repro code.

handleResponse was not handled correctly, as it not returned any value, and had no catch attached to it.
It also effectively was never correctly handled inside two other blocks with resp.then and PromisePrototypeCatch(PromisePrototypeThen(resp, "...")) as well, as it just short-circuited the promise with an empty resolve, instead of relying on the last (async () => {}) block.

This change makes handleResponse return a correct value and attach onError handler to the "non-thenable" variant of response handling code.

continues are redundant, as there are no unhandled branches within the for loop at line 540.


Repro from #17291

addEventListener("unhandledrejection", (event) => {
  console.error("Unhandled rejection:", event.reason);
});

Deno.serve(
  (request) => {
    const stream = new ReadableStream({
      start(controller) {
          controller.enqueue("Hello world");
          controller.close()
      },
      cancel(reason) {
        console.log("Request cancelled:", reason);
      },
    });

    return new Response(stream, {
      status: 200,
      headers: {
        "Content-Type": "text/html; charset=utf-8",
      },
    });
  },
  {
    port: 9000,
    onError: (err) => {
      console.error("Server Error:", err);
      return new Response("Internal Server Error", { status: 500 });
    },
  }
);
$ deno run -A --unstable mod.ts
$ curl localhost:9000

Before:

Listening on http:https://127.0.0.1:9000/
Unhandled rejection: TypeError: Expected ArrayBufferView at position 2
    at tryRespondChunked (deno:ext/flash/01_http.js:643:35)
    at deno:ext/flash/01_http.js:393:17

After:

Listening on http:https://127.0.0.1:9000/
Server Error: TypeError: Expected ArrayBufferView at position 2
    at tryRespondChunked (deno:ext/flash/01_http.js:641:35)
    at deno:ext/flash/01_http.js:393:17

Fixes #17291

@bartlomieju
Copy link
Member

Thanks @kamilogorek, any chance you could add a test that exercises this code path?

@kamilogorek
Copy link
Contributor Author

Sure thing, done

Copy link
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you

@bartlomieju bartlomieju merged commit 429ccff into denoland:main Jan 14, 2023
Clownsw pushed a commit to Clownsw/deno that referenced this pull request Jan 14, 2023
…nd#17303)

The leading cause of the problem was that `handleResponse` has
`tryRespondChunked` passed as an argument, which in turn is implemented
as a call to `core.ops.op_try_flash_respond_chuncked`, that throws in
the repro code.

`handleResponse` was not handled correctly, as it not returned any
value, and had no `catch` attached to it.
It also effectively was never correctly handled inside two other blocks
with `resp.then` and `PromisePrototypeCatch(PromisePrototypeThen(resp,
"..."))` as well, as it just short-circuited the promise with an empty
resolve, instead of relying on the last `(async () => {})` block.

This change makes `handleResponse` return a correct value and attach
`onError` handler to the "non-thenable" variant of response handling
code.
@kamilogorek kamilogorek deleted the handle-chunked-response-error branch January 15, 2023 11:45
bartlomieju pushed a commit that referenced this pull request Jan 16, 2023
The leading cause of the problem was that `handleResponse` has
`tryRespondChunked` passed as an argument, which in turn is implemented
as a call to `core.ops.op_try_flash_respond_chuncked`, that throws in
the repro code.

`handleResponse` was not handled correctly, as it not returned any
value, and had no `catch` attached to it.
It also effectively was never correctly handled inside two other blocks
with `resp.then` and `PromisePrototypeCatch(PromisePrototypeThen(resp,
"..."))` as well, as it just short-circuited the promise with an empty
resolve, instead of relying on the last `(async () => {})` block.

This change makes `handleResponse` return a correct value and attach
`onError` handler to the "non-thenable" variant of response handling
code.
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

Successfully merging this pull request may close these issues.

Unhandled rejection on http server
3 participants