* action: strip Content-Type on body-less apiFetch requests (#692) Vercel's Next.js lambda adapter (Next 16.1.x) attempts to decode a request body when Content-Type is set and throws `SyntaxError: Unexpected end of data` before delegating to the route handler, returning a 500. Hit /run-context exclusively because it was the only body-less GET that sent `Content-Type: application/json`. - Drop `Content-Type: application/json` from the GET in `action/utils/runContext.ts` (meaningless on a body-less request). - Defensively strip any `content-type` header in `action/utils/apiFetch.ts` when no body is present so future callers can't reintroduce this. * apiFetch: soften comment — empirical observation, RFC 9110 §8.3 framing
This commit is contained in:
committed by
pullfrog[bot]
parent
d8f825034f
commit
43bb14bf87
@@ -37,6 +37,18 @@ export async function apiFetch(options: ApiFetchOptions): Promise<Response> {
|
|||||||
headers["x-vercel-protection-bypass"] = bypassSecret;
|
headers["x-vercel-protection-bypass"] = bypassSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// never send Content-Type on body-less requests. empirically, Vercel's
|
||||||
|
// Next.js lambda adapter (Next 16.1.x) throws `SyntaxError: Unexpected
|
||||||
|
// end of data` before delegating to the route handler — returning a 500 —
|
||||||
|
// when Content-Type is set but no body is present. exact mechanism is
|
||||||
|
// unverified (minified runtime frame), but Content-Type on a body-less
|
||||||
|
// request has no defined semantics per RFC 9110 §8.3 anyway. see #692.
|
||||||
|
if (!options.body) {
|
||||||
|
for (const key of Object.keys(headers)) {
|
||||||
|
if (key.toLowerCase() === "content-type") delete headers[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.debug(`api fetch: ${options.method ?? "GET"} ${url.pathname}`);
|
log.debug(`api fetch: ${options.method ?? "GET"} ${url.pathname}`);
|
||||||
|
|
||||||
const init: RequestInit = {
|
const init: RequestInit = {
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ export async function fetchRunContext(params: {
|
|||||||
try {
|
try {
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
Authorization: `Bearer ${params.token}`,
|
Authorization: `Bearer ${params.token}`,
|
||||||
"Content-Type": "application/json",
|
|
||||||
};
|
};
|
||||||
if (params.oidcToken) {
|
if (params.oidcToken) {
|
||||||
headers["X-GitHub-OIDC-Token"] = params.oidcToken;
|
headers["X-GitHub-OIDC-Token"] = params.oidcToken;
|
||||||
|
|||||||
Reference in New Issue
Block a user