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

[Bug?]: Cannot read request body in middleware or api route using cloudflare #1287

Closed
2 tasks done
sabercoy opened this issue Jan 27, 2024 · 8 comments
Closed
2 tasks done
Labels
bug Something isn't working vinxi related to vinxi

Comments

@sabercoy
Copy link

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

/routes/api/test.ts

import { APIEvent, readBody} from "@solidjs/start/server";

export const POST = async (event: APIEvent) => {
  const body = await readBody(event)

  return new Response(body)
}

Wrangler gives the error when trying to parse the body, as well as cloudflare when actually deployed

✘ [ERROR] A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's I/O context have already finished.


✘ [ERROR] Uncaught (in response) Error: The script will never generate a response.

Expected behavior 🤔

give the parsed body and no error

Steps to reproduce 🕹

Steps:

  1. clone https://github.com/Numnumberry/solid-start-cf-body-error
  2. pnpm i
  3. pnpm run wrangler
  4. send a POST request to localhost:3000/api/test

Context 🔦

No response

Your environment 🌎

No response

@sabercoy sabercoy added the bug Something isn't working label Jan 27, 2024
@sabercoy
Copy link
Author

found a clue: readBody uses readRawBody which uses WritableStream
according to cloudflare, you cannot use WritableStream constructor on workers platform: https://developers.cloudflare.com/workers/runtime-apis/streams/writablestream/#writablestream

@sabercoy
Copy link
Author

sabercoy commented Jan 28, 2024

found a clue: readBody uses readRawBody which uses WritableStream according to cloudflare, you cannot use WritableStream constructor on workers platform: https://developers.cloudflare.com/workers/runtime-apis/streams/writablestream/#writablestream

I found out how to get the request body, so what I said about WritableStream may be irrelevant to this problem, but should probably be noted anyway.

I was able to retrieve the body in CF Workers by reading it from event.node.req.body.toString('utf8')

export async function POST(event: CustomAPIEvent) {
  const body = event.node.req.body.toString('utf8')
  return new Response(body)
}

In debugging and looking at the event object that cloudflare receives, I found 4 places that request/body occur:

  event.node.req.body
  event.request.body
  event.web.request.body
  event.context.cloudflare.request.body

event.node.req.body was a Buffer
event.request.body was a ReadableStream (locked with length undefined)
event.web.request.body was a ReadableStream (locked with length undefined)
event.context.cloudflare.request.body was a ReadableStream (NOT locked with a length)

I believe the workers were throwing the hanging Promise error because the implementation of readBody was trying to read from a body that was already used in one of these 4 locations.

This is probably all expected or obvious to maintainers, but just wanted to leave my findings here in case they help with developing SolidStart's API, because how I am doing it is probably just a stop gap and not the intended way.

@ryansolid
Copy link
Member

Thanks for reporting. Stuff like this shouldn't impact how we want to approach our API. This should be handled at the runtime level. I will tag this appropriately and forward it on.

@ryansolid ryansolid added the vinxi related to vinxi label Jan 29, 2024
@ryansolid
Copy link
Member

Question, does it work if you try to get it off the request.

Like:

const body = await event.request.text()

The reason I ask is preferably we are pushing people towards that interface and it occurs to me that readBody might be grabbing from a non-web location which is causing issues. We've seen it elsewhere. But it seemed to have been resolved. I suppose this might be cloudflare specific.

@sabercoy
Copy link
Author

Question, does it work if you try to get it off the request.

event.request.text() fails in the originally-posted test case the same as readBody()

"@solidjs/meta": "^0.29.2",
"@solidjs/router": "^0.10.10",
"@solidjs/start": "^0.4.10",
"solid-js": "^1.8.12",
"vinxi": "^0.1.6"

However...

I pulled down the latest solid@latest and reran the test:
event.request.text() succeeds
event.request.json() succeeds
readBody(event) succeeds

"@solidjs/meta": "^0.29.2",
"@solidjs/router": "^0.12.0",
"@solidjs/start": "^0.5.5",
"solid-js": "^1.8.14",
"vinxi": "^0.2.1"

It seems it works locally on wrangler!

@sabercoy
Copy link
Author

wait there is no readBody in this version, I must have tested the wrong server, let me try again

@sabercoy
Copy link
Author

yeah .text() and .json() both seems to work, I guess this is the expected way to go now?

@nksaraf
Copy link
Member

nksaraf commented Feb 20, 2024

I guess we can close this then. Please reopen if the issue persists with the latest solid-start and solid versions

@nksaraf nksaraf closed this as completed Feb 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working vinxi related to vinxi
Projects
None yet
Development

No branches or pull requests

3 participants