Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Svelte/Sapper: Body empty on POST

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.

like image 971
Toby King Avatar asked Jul 16 '20 14:07

Toby King


People also ask

What is the difference between Sapper and svelte?

Powered by Svelte. Sapper is an application framework powered by Svelte — build bigger apps with a smaller footprint.

Does sveltekit support parsing of body as an object?

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.

What is Sapper?

What is Sapper? Sapper is a framework for building extremely high-performance web apps. You're looking at one right now! There are two basic concepts: You create pages by adding files to the src/routes directory of your project.

What happens when I run Sapper export?

When you run sapper export, Sapper first builds a production version of your app, as though you had run sapper build, and copies the contents of your static folder to the destination. It then starts the server, and navigates to the root of your app.


2 Answers

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);
    });
like image 194
Stephane Vanraes Avatar answered Sep 16 '22 20:09

Stephane Vanraes


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>
like image 27
Carlos Roso Avatar answered Sep 17 '22 20:09

Carlos Roso