Skip to content

Conversation

@dummdidumm
Copy link
Member

Fixes #7514

I'm not sure if this is the best approach. I'm a little nervous because cloning the whole Request body might become costly, and since we can't read the body only when absolutely needed (because the ReadableStream is already consumed by then) we have to do it unconditionally. I would hope though that people calling fetch like this are in the minority.

A different solution would be to somehow give the request another kind of ID, like a call index, but that could be messed up if the user does something with if (browser) fetch(..).

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. All changesets should be patch until SvelteKit 1.0
@changeset-bot
Copy link

changeset-bot bot commented Nov 7, 2022

🦋 Changeset detected

Latest commit: be2cc5a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Rich-Harris
Copy link
Member

I see two possibilities:

  1. Clone the body in the fetch(request) case (as is currently the case in this PR)
  2. Bail in the fetch(request) case where request.method !== 'GET' (i.e. the request is repeated for real in the client)

Option 2 is 'safer', in that it doesn't matter how big the request body is. But in reality no-one is going to be making requests with huge bodies in the context of a load function, because GraphQL is the only realistic use case for POST requests in the first place. So I think my vote goes for option 1, despite it feeling somewhat unclean

(Aside: the fact that GraphQL queries can be large enough that we're forced to use POST requests in the first place is really just a symptom of how daft the whole thing is.)

Comment on lines 154 to 156
input instanceof Request && cloned_body
? await streamToString(cloned_body)
: init?.body
Copy link
Member

Choose a reason for hiding this comment

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

one thought — if request_body could be a ReadableStream...

Suggested change
input instanceof Request && cloned_body
? await streamToString(cloned_body)
: init?.body
init?.body ?? input.clone?.().body

...then later, in render.js, we could do something like this:

if (page_config.ssr && page_config.csr) { +for (const request of fetched) { +if (fetched.request_body instanceof ReadableStream) { +fetched.request_body = await to_string(fetched.request_body); +} +}	body += `\n\t${fetched	.map((item) =>	serialize_data(item, resolve_opts.filterSerializedResponseHeaders, !!state.prerendering)	)	.join('\n\t')}`;	}

Though it may actually be cheaper to keep the entire request clone and then do

fetched.request_body = await fetched.clone.arrayBuffer();

than to implement our own stream to string function

Copy link
Member Author

Choose a reason for hiding this comment

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

That doesn't work, because cloning the request at that point is too late, the body's ReadableStream is already consumed by then and you can't get the value.

Copy link
Member

Choose a reason for hiding this comment

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

oh, of course 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants