I am attempting to build a static site with Astro, but I want to add a component that allows a user to sign up for a newsletter via an HTML form. Following Astro's guides, I am using an API endpoint to accept the form data and process the logic. However, when submitting the form, I get an error, Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded"
when calling await request.formData();
. As far as I can see by looking at the headers in the request though, it is encoded as multipart/form-data:
Content-Type: multipart/form-data;boundary=---------------------------30448001245691757982165322994
And the payload:
-----------------------------30448001245691757982165322994
Content-Disposition: form-data; name="email"
test@test.com
-----------------------------30448001245691757982165322994--
The API endpoint code (from the Astro docs):
import type { APIRoute } from "astro";
export const POST: APIRoute = async ({ request }) => {
const data = await request.formData(); // error is thrown here
const email = data.get("email");
// Validate the data - you'll probably want to do more than this
if (!email) {
return new Response(
JSON.stringify({
message: 'Missing required fields',
}),
{ status: 400 }
);
}
// Do something with the data, then return a success response
return new Response(
JSON.stringify({
message: "Success!"
}),
{ status: 200 }
);
}
And the javascript to send the request:
const formData = new FormData(event.currentTarget as HTMLFormElement);
const response = await fetch("/api/newsletter", {
method: "POST",
body: formData,
});
const apidata = await response.json();
The problem was with Astro prerendering the API endpoint. Since I had Astro configured for output: hybrid
, I needed to explicitly tell Astro not to prerender the API endpoint.
Adding export const prerender = false;
at the top of the API endpoint code resolved the issue.