1

I am trying to Build a form submission handler for JS-free form submission. But the api is not receiving the data sent by the html form. I am following this documentation.

The signin.json.js file contains an export async function called post that takes in a request parameter and logs it to the console. It then returns a new Response object with the request parameter stringified as JSON and a status of 200.

The index.astro file contains an HTML form with an action of /api/signin.json and a method of post. It has two input fields, one of type text with the name text and a value of test, and the other of type submit.

Upon form submission, the output in the terminal shows the request object that was logged to the console. However, the output in the browser shows a JSON object with several properties, but none of them contain the data that was submitted in the form. It is unclear why the data from the form is not being received by the API. It could be a problem with the form itself, the way the data is being processed by the post function, or something else.

In the Astro JS directory my files are at

  1. /pages/signin.json.js
  2. /pages/index.astro

Code // signin.json.js

export async function post({request}) {
    console.log(request)
  return new Response(JSON.stringify(request), {
    status: 200,    
  });
}

// index.astro

---
---

<form action="/api/signin.json" method="post" >
                <input type='text' name='text' value='test' />
                <input type="submit" />
            </form>

Output after submit

Terminal

Request {
  size: 0,
  follow: 20,
  compress: true,
  counter: 0,
  agent: undefined,
  highWaterMark: 16384,
  insecureHTTPParser: false,
  [Symbol(Body internals)]: {
    body: <Buffer 74 65 78 74 3d 61 73 61>,
    stream: Readable {
      _readableState: [ReadableState],
      _read: [Function: read],
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      [Symbol(kCapture)]: false
    },
    boundary: null,
    disturbed: false,
    error: null
  },
  [Symbol(Request internals)]: {
    method: 'POST',
    redirect: 'follow',
    headers: {
      accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
      'accept-encoding': 'gzip, deflate, br',
      'accept-language': 'en-US,en',
      'cache-control': 'max-age=0',
      connection: 'keep-alive',
      'content-length': '8',
      'content-type': 'application/x-www-form-urlencoded',
      cookie: 'io=NH8tzNimTmy0AtvFAAAA; asasa=asaa',
      host: 'localhost:3000',
      origin: 'http://localhost:3000',
      referer: 'http://localhost:3000/login',
      'sec-fetch-dest': 'document',
      'sec-fetch-mode': 'navigate',
      'sec-fetch-site': 'same-origin',
      'sec-fetch-user': '?1',
      'sec-gpc': '1',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
    },
    parsedURL: URL {
      href: 'http://localhost:3000/api/signin.json',
      origin: 'http://localhost:3000',
      protocol: 'http:',
      username: '',
      password: '',
      host: 'localhost:3000',
      hostname: 'localhost',
      port: '3000',
      pathname: '/api/signin.json',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    },
    signal: null,
    referrer: undefined,
    referrerPolicy: ''
  },
  [Symbol(astro.clientAddress)]: '::1'
}

Browser

{
"size": 0,
"follow": 20,
"compress": true,
"counter": 0,
"highWaterMark": 16384,
"insecureHTTPParser": false
}

I verified that the form action and method are correct and match the expected endpoint and HTTP verb. In this case, the form action is /api/signin.json and the method is post, which seem to be correct based on the code provided.

that's my config file // astro.config.mjs

import { defineConfig } from 'astro/config';
import netlify from "@astrojs/netlify/functions";
import svelte from "@astrojs/svelte";

// https://astro.build/config
export default defineConfig({
  output: "server",
  adapter: netlify(),
  integrations: [svelte()]
});
KayD
  • 746
  • 5
  • 15

2 Answers2

1

Here's a way to handle forms:

// pages/index.astro

<form action="/api/signin" method="post" >
        <input type='text' name='text' value='asa' />
        <input type="submit" />
</form>

Now the endpoint

// pages/api/signin.js
export async function post({request}) {
  const data = await request.formData(); // Here's the data sent by the form
  const text = data.get('text'); // Here's how you get the value of a field
  console.log(text);
  return new Response(JSON.stringify(request), {
    status: 200,
  });
}
HappyDev
  • 380
  • 1
  • 9
1

The body property in the request obj is a readable stream. You can read that but it is async so you must await it. If you called the endpoint with a post request sending json data (and expecting json back) it would look like this.

export const post: APIRoute = async ({ request }) => {

  if (request.headers.get('Content-Type') === 'application/json') {
    const formData = await request.json()
    const name = formData.name
    return new Response(
      JSON.stringify({
        message: 'Your name was: ' + name,
      }),
      {
        status: 200,
      }
    )
  }
  return new Response(null, { status: 400 })
}

In your case you are requesting the endpoint like a page from the form. You will either have return some html or redirect to a url.

A redirect is the most sensible I guess and can be done with:

return redirect(link, 307);

link is a relative or absolute path/url.

Most of the code above is from the documentation