Body Parsing
LiteNode includes built-in support for parsing request bodies — no middleware setup required. It automatically handles JSON, URL-encoded form data, and multipart/form-data.
Accessing the Body
Two equivalent styles are available. Use whichever you prefer:
// Via req.body
app.post("/users", (req, res) => {
const data = req.body
res.status(201).json({ created: data })
})
// Via the third handler parameter
app.post("/users", (req, res, data) => {
res.status(201).json({ created: data })
})
Supported HTTP Methods
Body parsing is automatic for:
POST— creating resourcesPUT— replacing resourcesPATCH— partial updatesDELETE— when a payload is needed alongside deletion
Request Size Limit
Pass a number as the last argument to set a maximum request size in megabytes. The default is 1 MB.
// 512 KB limit
app.post("/upload", handleUpload, 0.5)
// 5 MB limit for larger payloads
app.patch("/update-image", handleImageUpdate, 5)
Supported Content Types
JSON
Send Content-Type: application/json from the client. The body is parsed into a JavaScript object automatically:
app.post(
"/register",
async (req, res, data) => {
const { username, email, password } = data
if (!username || !email || !password) {
return res.status(400).json({ error: "Missing required fields" })
}
// proceed with registration...
res.status(201).json({ message: "User registered" })
},
0.5,
)
URL-encoded Form Data
Standard HTML form submissions (application/x-www-form-urlencoded) are parsed automatically. LiteNode detects the encoding type — the enctype attribute on the form is optional.
Bracket notation in field names produces nested objects on the server:
<!-- form field: file[title] -->
<input type="text" name="file[title]" />
app.post("/create-file", (req, res, data) => {
const { file } = data
// file.title, file.description, etc.
res.status(201).json({ message: "File created" })
})
multipart/form-data
Used for file uploads. LiteNode uses meros (1 KB) internally to parse multipart data efficiently.
Every field in a multipart form — whether a file or a plain text input — arrives as an array of objects. This is different from JSON and URL-encoded forms, where text fields are plain strings.
Each part object exposes:
| Property | File field | Text field |
|---|---|---|
filename |
Original filename from the client | null |
body |
Binary file content (Buffer) |
Field value as a UTF-8 Buffer |
contentType |
MIME type of the file | text/plain or empty string |
headers |
Raw part headers | Raw part headers |
File-only upload
import { writeFile } from "node:fs/promises"
app.post(
"/upload",
async (req, res, data) => {
const { files } = data
for (const file of files) {
await writeFile(`uploads/${file.filename}`, file.body)
}
res.redirect("/uploads")
},
5,
)
Mixed form: file + text fields
When a form includes both a file input and text fields alongside it, all fields follow the same array-of-objects shape. Text field values must be read from the body Buffer:
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
<input type="text" name="username" />
<input type="number" name="age" />
<button type="submit">Save</button>
</form>
import { writeFile } from "node:fs/promises"
app.post(
"/profile",
async (req, res, data) => {
// Files: use .body directly as a Buffer
const avatar = data.avatar?.[0]
// Text fields: .body is a Buffer — convert it to a string first
const username = data.username?.[0]?.body.toString("utf-8").trim()
const age = parseInt(data.age?.[0]?.body.toString("utf-8"), 10)
if (!avatar || !username || isNaN(age)) {
return res.status(400).json({ error: "Missing required fields." })
}
await writeFile(`avatars/${avatar.filename}`, avatar.body)
res.status(201).json({ username, age })
},
2,
)
For forms with many text fields, a small helper keeps the extraction concise:
// Returns the string value of a multipart text field, or a fallback
function getField(data, name, fallback = "") {
const field = data[name]
if (!field || !Array.isArray(field) || !field[0]) return fallback
return field[0].body.toString("utf-8").trim() || fallback
}
app.post(
"/profile",
async (req, res, data) => {
const avatar = data.avatar?.[0]
const username = getField(data, "username")
const age = parseInt(getField(data, "age"), 10)
if (!avatar || !username || isNaN(age)) {
return res.status(400).json({ error: "Missing required fields." })
}
await writeFile(`avatars/${avatar.filename}`, avatar.body)
res.status(201).json({ username, age })
},
2,
)
See the Examples page for full client + server examples for each content type.