Parsing request.body/event.body throwing error

I’m experiencing a problem in serverless function, when I log out request/event body which is a stringify form data it log out the value as request.body/event.body with body having the following property (1) stream with the value of false, length with the bytes length as it should be and source which is the data and it’s a string of key values pair but when I log out body.source it become a readable stream.

When I read it with a stream reader and iterate over it it’s a unitArray of bytes which is normal with readable stream but when I parse the whole body/body.source I get an error.

First I don’t know why a value of steam=false turn to readable stream , when I tried to log out the value of the body.source or body it become a readable stream but when the whole event/request is logged out it log out the whole body with each property being what it suppose to be and then cherry picking a property like the source which is the actual data throw when it’s parsed or become a stream when it’s log.

I need the to parse the body else this is useless as I can’t do anything with it and reading it as a readable stream is overhead and more codes than I wish for. Any help will be appreciated.

Front End Code:

function processContactData() {
 const contactForm = document.querySelector('#contact')
 const contactFormCta = document.querySelector('.contact--cta')
 const url = contactForm.action
 async function handleContact(formData) {
   const res = await (await fetch(url, formData)).json()
   console.log(res)
   const feedBack = document.createElement('p')
   if (res.status == '200' || res.status == '201') {
     feedBack.style = 'text-text-fluid--2 text-text-1 bg-surface-2'
     feedBack.textContent(
       'Thank you for contacing me. Looking forward to working with you!'
     )
     contactFormCta.insertAdjacentElement('afterend', feedBack)
     contactForm.reset()
   } else {
     feedBack.style = 'text-text-fluid--2 text-text-1 bg-surface-2'
     feedBack.textContent(
       'Sorry something went wrong, please submit the form again'
     )
     contactFormCta.insertAdjacentElement('afterend', feedBack)
   }
 }

 contactForm.addEventListener('submit', async (e) => {
   e.preventDefault()
   const contactData = new FormData(e.target)
   const contactPayload = {
     body: JSON.stringify({
       fullname: contactData.get('fullname'),
       email: contactData.get('email'),
       company: contactData.get('company'),
       purpose:
         (contactData.get('fulltime') && 'fulltime') ||
         (contactData.get('parttime') && 'parttime') ||
         (contactData.get('contract') && 'contract') ||
         (contactData.get('other') && 'other'),
       message: contactData.get('message'),
     }),
     //headers: { 'Content-Type': 'application/json' },
     method: 'POST',
   }

   handleContact(contactPayload)
 })
}
document.addEventListener('DOMContentLoaded', processContactData)

Serverless Function Code:

export default async (request) => {
 let parsedBody;
  console.log(request) // Log out the whole request obj
  parsedBody = JSON.parse(request) // Suppose to parse the body obj
  //parsedBody =  JSON.parse(request.body.source) // source hold the actual data This also throw Error
 console.log(parsedBody) // Throw Error by JSON.parse()
  for await (const chunk of reqBody) {
  console.log(chunk)
  } // Log out readable steam of UnitArray in bytes
 
 return new Promise('worked', {
    status: 200,
    header: { 'content-type': 'application/json' },
    body: 'WIP',
  }) // 500 is returned as response to the front end because of the aforementioned issue
 
export const config = {
  path: '/contact-form',
}

Did you try request.body: Request: body property - Web APIs | MDN (mozilla.org). You can also use request.json: Request: json() method - Web APIs | MDN (mozilla.org) for JSON bodies.

@hrishikesh Thank you for your response, Yes I did as I mentioned in the post but Now arrises more quirkiness. I will post the new code for the Serverless here as it is now this is working, I’m getting a 200 status from the client and a full response object and I’m able to parse the request body, however this code uses the old way by exporting an handler with the Node module syntax and also using the old way of url path which include ‘/.netlify/functions/’ and returning an object as a response with the following property statusCode, body and headers.

CLIENT SIDE FOR THE WORKING IMPLEMENTATION

function processContactData() {
  const contactForm = document.querySelector('#contact')
  const contactFormCta = document.querySelector('.contact--cta')
  //const url = contactForm.action
async function handleContact(formData) {
    const res = await fetch('/.netlify/functions/contact-form', formData)
    //const res = await fetch(url, formData)
    console.log(res)
    const feedBack = document.createElement('p')
    if (res.status == '200' || res.status == '201') {
      feedBack.style = 'text-text-fluid--2 text-text-1 bg-surface-2'
      feedBack.textContent =
        'Thank you for contacing me. Looking forward to working with you!'
      contactFormCta.insertAdjacentElement('afterend', feedBack)
      contactForm.reset()
    } else {
      feedBack.style = 'text-text-fluid--2 text-text-1 bg-surface-2'
      feedBack.textContent =
        'Sorry something went wrong, please submit the form again'

      contactFormCta.insertAdjacentElement('afterend', feedBack)
    }
  }

  contactForm.addEventListener('submit', async (e) => {
    e.preventDefault()
    const contactData = new FormData(e.target)
    const contactPayload = {
      body: JSON.stringify({
        fullname: contactData.get('fullname'),
        email: contactData.get('email'),
        company: contactData.get('company'),
        purpose:
          (contactData.get('fulltime') && 'fulltime') ||
          (contactData.get('parttime') && 'parttime') ||
          (contactData.get('contract') && 'contract') ||
          (contactData.get('other') && 'other'),
        message: contactData.get('message'),
      }),
      //headers: { 'Content-Type': 'application/json' },
      method: 'POST',
    }

    handleContact(contactPayload)
  })
}
document.addEventListener('DOMContentLoaded', processContactData)

SERVERLESS FUNCTION IMPLEMENTATION THAT WORK

exports.handler = async (request) => {
  const parsedBody = request.body
  console.log(parsedBody)
  return {
    statusCode: 200,
    heaeder: { 'content-type': 'application/json' },
    body: JSON.stringify('WIP'),
  }
  
}

When I tried the new syntax by exporting the function with MJS syntax and returning a Promise obj while including a config object as the path I’m still able to parse the request body but now the client side is broken as the response seem to be hanging or not reaching the client side. Checking the network utils in the browser I see which never resolved because the client didn’t log the response to the console or branch to the code part that rely on the status code also I noticed the cli didn’t not log out the response either as it does when using the old syntax.

SERVERLESS IMPLEMENTATION WORKING BUT CLIENT SIDE NOT GETTING RESPONSE
Note: Change the url in the client fetch to ‘/contact-form’ corresponding to config path exported by the serverless function

export default async (request) => {
  const parsedBody = await request.json()
  console.log(parsedBody)
  return new Response('Worked',  {
    statusCode: 200, // or status:200
    heaeder: { 'content-type': 'application/json' },
    body: JSON.stringify('WIP'),
  })
}
 
export const config = {
path: '/contact-form',
}

The included codes should be enough to reproduce. Please let me know if this quirkiness is from my side, a bug from your ends or whatever it is, right now I’m going to count my loss and stick with the working old syntax . Thanks again for your response.

I think you’re mixing the old and the new API. In old API, the parameter:

is not request, but event.

In the new format, you don’t need to return a statusCode or a body:

Check out this example: JSON Response | Edge Functions on Netlify (edge-functions-examples.netlify.app)