diff --git a/.changeset/blue-dots-march.md b/.changeset/blue-dots-march.md new file mode 100644 index 000000000..d96ed70c4 --- /dev/null +++ b/.changeset/blue-dots-march.md @@ -0,0 +1,5 @@ +--- +"@solidjs/start": patch +--- + +Fixed an issue where runtimes like AWS Lambda would default to `application/json` when no header was present, causing parsing errors in `json` serialization mode. To ensure consistent behavior, the `Content-Type` is now explicitly set to `text/plain`. diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts index a7007fee0..0da405aa5 100644 --- a/packages/start/src/runtime/server-handler.ts +++ b/packages/start/src/runtime/server-handler.ts @@ -154,6 +154,10 @@ async function handleServerFunction(h3Event: HTTPEvent) { setHeader(h3Event, "content-type", "text/javascript"); return serializeToJSStream(instance, result); } + // Explicitly set the Content-Type to avoid runtimes (e.g., AWS Lambda) + // that default to `application/json`, which can break serialization + // when the SEROVAL output is not valid JSON. + setHeader(h3Event, "content-type", "text/plain"); return serializeToJSONStream(result); } catch (x) { if (x instanceof Response) { @@ -181,6 +185,10 @@ async function handleServerFunction(h3Event: HTTPEvent) { setHeader(h3Event, "content-type", "text/javascript"); return serializeToJSStream(instance, x); } + // Explicitly set the Content-Type to avoid runtimes (e.g., AWS Lambda) + // that default to `application/json`, which can break serialization + // when the SEROVAL output is not valid JSON. + setHeader(h3Event, "content-type", "text/plain"); return serializeToJSONStream(x); } return x; diff --git a/packages/start/src/runtime/server-runtime.ts b/packages/start/src/runtime/server-runtime.ts index baec39ea5..e28975121 100644 --- a/packages/start/src/runtime/server-runtime.ts +++ b/packages/start/src/runtime/server-runtime.ts @@ -77,16 +77,16 @@ async function fetchServerFunction( const contentType = response.headers.get("Content-Type"); const cloned = response.clone(); let result; - if (contentType && contentType.startsWith("text/plain")) { - result = await cloned.text(); - } else if (contentType && contentType.startsWith("application/json")) { - result = await cloned.json(); - } else if (response.headers.get("x-serialized")) { + if (response.headers.get("x-serialized")) { if (import.meta.env.SEROVAL_MODE === "js") { result = await deserializeJSStream(instance, cloned); } else { result = await deserializeJSONStream(cloned); } + } else if (contentType && contentType.startsWith("text/plain")) { + result = await cloned.text(); + } else if (contentType && contentType.startsWith("application/json")) { + result = await cloned.json(); } if (response.headers.has("X-Error")) { throw result;