Return JSON

A page sends HTML by default. This guide shows you how to send JSON, redirects, downloads, CSV, and streams instead.
status.cow
<?js
res.json({ message: 'All good in the pasture.' })
Output — /status
{"message":"All good in the pasture."}
When you pass a value to res.json(), Cow sends JSON and finishes the response. Calling it without a value only selects the JSON content type.

Redirect a visitor

Redirect
res.redirect('/thanks')
Without a status argument, the response is a 302 redirect with a location header.
Set status and headers before response output is committed. Methods that finish the response should be the last response operation in that path.

Offer a download

download.cow
<?js
// Check the visitor is allowed to access this file first.
res.type('application/pdf')
await res.download(__dirname + '/../data/report.pdf', 'report.pdf')
Warning: Use an authorized, server-chosen absolute path.
res.sendFile() sends a file without an attachment name. You must await both operations.

Export CSV

export.cow
<?js
import { stringifyCsv } from 'cow:csv'
res.type('text/csv; charset=utf-8')
res.send(stringifyCsv([
  ['name', 'message'],
  ['Clover', 'Hello, herd!']
]))
Output — /export
name,message
Clover,"Hello, herd!"
CSV helpers read and write text.
Warning: CSV quoting does not neutralize spreadsheet formulas in untrusted cells. Handle that separately when you export to spreadsheets.

Stream a response

stream.cow
<?js
res.type('text/plain; charset=utf-8')
async function* lines() {
  yield 'Hello, herd!\n'
  yield 'That is all for now.\n'
}
await res.stream(lines())
Streams stay within the request lifetime. A failure after output begins closes the response. Cow cannot replace bytes that it already sent with an error page.