Svelte/Sapper: Body empty on POST
Asked Answered
S

2

5

I'm trying to create a login form using sapper, but am encountering the following problem when trying to test a basic POST fetch.

In routes/login/login.svelte, I have the following code which is called on a button click:

<script>
  let data = {"email":"test"};

  const handleLogin = async () => {
    const response = await fetch("/login/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: data
    });
  };
</script>

Which should send what is in data to routes/login/login.js which has the following code:

export async function post(req, res, next) {
  res.setHeader('Content-Type', 'application/json');
  var data = req.body;
  return res.end(JSON.stringify(data));
}

My problem is that this only returns {} rather than the data sent in the svelte page. Any ideas as to why this is happening and where I'm going wrong? Thanks.

Snout answered 16/7, 2020 at 14:9 Comment(0)
A
4

When sending the data, you should also stringify it there

   body: JSON.stringify(data)

as an extra make sure you have body-parser installed and added as middleware in the server, this package will help you handle requests that have send json data in their body.

polka() // You can also use Express
    .use(
        compression({ threshold: 0 }),
        sirv('static', { dev }),
        bodyparser(),
        sapper.middleware()
    )
    .listen(PORT, err => {
        if (err) console.log('error', err);
    });
Aerobatics answered 16/7, 2020 at 17:13 Comment(3)
Thanks for the reply, I've added the JSON.stringify bit and imported json from bodyparser but am still receiving a blank return for some reasonSnout
Not bodyparser() but bodyParser.json()Dhammapada
The response object in your code will not contain the actual json data returned, for that you have to do response.json() which returns a promise. You can do fetch(...).then(res => res.json()) to get the json data directly in response. (This assumes no errors were returned from the server though)Aerobatics
S
3

Building on the previous answer, I'm writing here the full working solution. Your problems may be due to:

  1. Not using the json parse middleware
  2. Not treating fetch as a promise

Here's how I'd fix it:

  1. npm i body-parser
  2. Add the json middleware in your server.js
const { json } = require('body-parser');

polka()
    .use(
      compression({ threshold: 0 }),
      json(),
      sirv('static', { dev }),
      sapper.middleware()
    )
    .listen(PORT, err => {
        if (err) console.log('error', err);
    });
  1. Treat the fetch response as a Promise. This is how your Svelte component should look like (notice the chained then):
<script>
  let data = {"email":"test"};

  const handleLogin = async () => {
    await fetch(`your-endpoint`, {
      method: 'POST',
      body: JSON.stringify(data),
      headers:{
        'Content-Type': 'application/json'
      }
    })
    .then(res => res.json())
    .then(res => console.log(res)); // {email: "test"}

  };
</script>
Slip answered 20/7, 2020 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.