Skip to content

Commit

Permalink
Actions: fix 500 on empty object for Vercel serverless (#11634)
Browse files Browse the repository at this point in the history
* fix: only set content-type when body is defined

* feat(test): content-type is omitted

* chore: changeset
  • Loading branch information
bholmesdev authored Aug 6, 2024
1 parent d532df1 commit 2716f52
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-poems-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes internal server error when calling an Astro Action without arguments on Vercel.
Binary file added packages/astro/astro-4.13.1.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/astro/src/actions/runtime/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const POST: APIRoute = async (context) => {
const contentType = request.headers.get('Content-Type');
const contentLength = request.headers.get('Content-Length');
let args: unknown;
if (contentLength === '0') {
if (!contentType || contentLength === '0') {
args = undefined;
} else if (contentType && hasContentType(contentType, formContentTypes)) {
args = await request.clone().formData();
Expand Down
9 changes: 6 additions & 3 deletions packages/astro/templates/actions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,18 @@ async function handleAction(param, path, context) {
let body = param;
if (!(body instanceof FormData)) {
try {
body = param ? JSON.stringify(param) : undefined;
body = JSON.stringify(param);
} catch (e) {
throw new ActionError({
code: 'BAD_REQUEST',
message: `Failed to serialize request body to JSON. Full error: ${e.message}`,
});
}
headers.set('Content-Type', 'application/json');
headers.set('Content-Length', body?.length.toString() ?? '0');
if (body) {
headers.set('Content-Type', 'application/json');
} else {
headers.set('Content-Length', '0');
}
}
const rawResult = await fetch(`/_actions/${path}`, {
method: 'POST',
Expand Down
23 changes: 21 additions & 2 deletions packages/astro/test/actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,18 +234,37 @@ describe('Astro Actions', () => {
});
});

it('Sets status to 204 when no content', async () => {
it('Sets status to 204 when content-length is 0', async () => {
const req = new Request('http://example.com/_actions/fireAndForget', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': '0',
},
});
const res = await app.render(req);
assert.equal(res.status, 204);
});

it('Sets status to 204 when content-type is omitted', async () => {
const req = new Request('http://example.com/_actions/fireAndForget', {
method: 'POST',
});
const res = await app.render(req);
assert.equal(res.status, 204);
});

it('Sets status to 415 when content-type is unexpected', async () => {
const req = new Request('http://example.com/_actions/fireAndForget', {
method: 'POST',
body: 'hey',
headers: {
'Content-Type': 'text/plain',
},
});
const res = await app.render(req);
assert.equal(res.status, 415);
});

it('Is callable from the server with rewrite', async () => {
const req = new Request('http://example.com/rewrite');
const res = await app.render(req);
Expand Down

0 comments on commit 2716f52

Please sign in to comment.