Chapter 8

Handling Body Data

Read JSON, text, and form bodies from incoming requests.

Handling Body Data

Request bodies are async because the server may receive them as a stream. Mark the handler async before reading JSON, text, or form data.

app.post('/api/chapters', async (c) => {
  const body = await c.req.json()
  return c.json({ received: body })
})

JSON bodies

Use c.req.json() for application/json requests.

type ChapterInput = {
  title: string
  description: string
}

app.post('/api/chapters', async (c) => {
  const input = await c.req.json<ChapterInput>()
  return c.json({ title: input.title }, 201)
})

Parsing reads the body once. If multiple parts of your app need body values, validate or parse early and pass the result forward.

Form bodies

For forms and file uploads, use parseBody().

app.post('/contact', async (c) => {
  const body = await c.req.parseBody()
  const email = body.email

  if (typeof email !== 'string') {
    return c.text('Email is required', 400)
  }

  return c.text(`Thanks, ${email}`)
})

parseBody() handles multipart/form-data and application/x-www-form-urlencoded requests. Values can be strings or files, so check the type before using them.

Text bodies

Use c.req.text() when the request is plain text.

app.post('/notes', async (c) => {
  const note = await c.req.text()
  return c.text(`Saved ${note.length} characters`)
})

For most applications, body handling should be paired with validation so handlers can work with trusted data.