Quick Tip: SvelteKit Endpoint Body Parsing

Photo by Jordan Harrison / Unsplash

While building out the SvelteKit application for an upcoming tutorial I ran into a peculiar issue with the request body: the content was populated but I was receiving undefined whenever I tried to access its properties.

export const post: RequestHandler<void, { username: string }> = 
async ({ body }) => {
  console.log(body); // {"username":"username", "password":"password"}

  const { username } = body;

  console.log(username); // undefined

...

If we take a look at the frontend code we can start to piece together what's happening:

const onSubmit = async () => {
  await fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify({
      username,
      password
  })
});

We're using fetch to send a POST request to our server and it requires us to send the body as a string. Despite typing the RequestHandler as an object it's simply passing along that string!

SvelteKit natively supports parsing incoming data as an object as long as the Content-Type: application/json header is added to the request. This is what the updated code looks like:

const onSubmit = async () => {
  await fetch('/api/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      username,
      password
  })
});

And now we'll see that our problem is fixed! 🎉

export const post: RequestHandler<void, { username: string }> = 
async ({ body }) => {
  console.log(body); // { username: "username", password: "password"}

  const { username } = body;

  console.log(username); // username

...

Alternate Solution

Another approach would be to explicitly call JSON.parse on the incoming JSON string. Note that I switched to properly typing the RequestHandler body as a string.

export const post: RequestHandler<void, string> = async ({ body }) => {
  console.log(body); // {"username":"username", "password":"password"}

  const { username } = JSON.parse(body);
	
  console.log(username); // username

...

Wrapping Up

Hopefully this saves someone some time 😅. This issue reminds us that Typescript is not a strongly typed language. Where other languages would have thrown an error at the mistyped RequestHandler body, Typescript was happy to pass along a string masquerading as an object!

Mags
Founder of Mags.ai. Building an open community of motivated learners