Home

Request & Response Objects

Learn how to work with HTTP requests and responses in Kempo Server.

Request Object

Kempo Server provides a request object that makes working with HTTP requests easier:

Properties

Methods

Body Parsing

request.body is eagerly parsed before your route handler runs. The parsing strategy depends on the Content-Type header:

Content-Typerequest.body value
application/jsonParsed object via JSON.parse(). If parsing fails, null.
application/x-www-form-urlencodedParsed object via URLSearchParams
No body (GET, HEAD, Content-Length: 0)null
Any other Content-TypeRaw string

The convenience methods request.json(), request.text(), and request.buffer() still exist and return promises for backward compatibility, but they resolve immediately from the cached body.

Response Object

Kempo Server also provides a response object that makes sending responses easier:

Methods

Request Examples

Accessing Route Parameters

// api/user/[id]/GET.js
export default async function(request, response) {
const { id } = request.params;
const { includeDetails } = request.query;

// Fetch user data from database
const userData = await getUserById(id);

if (!userData) {
return response.status(404).json({ error: 'User not found' });
}

response.json(userData);
}

Handling JSON Data

// api/user/[id]/POST.js
export default async function(request, response) {
const { id } = request.params;
const { name, email } = request.body;

// request.body is already parsed from JSON
const updatedUser = await updateUser(id, { name, email });

response.json(updatedUser);
}

Working with Form Data

// contact/POST.js
// With Content-Type: application/x-www-form-urlencoded,
// request.body is automatically parsed into an object
export default async function(request, response) {
const { name, email, message } = request.body;

await sendContactEmail({ name, email, message });

response.html('<h1>Thank you for your message!</h1>');
}

Checking Headers

// api/upload/POST.js
export default async function(request, response) {
// Check if request contains JSON data
if (request.is('application/json')) {
const data = await request.json();
// Handle JSON data
}

// Check specific headers
const authHeader = request.get('authorization');
const userAgent = request.get('user-agent');

// Check request method
if (request.method === 'POST') {
// Handle POST request
}

response.json({ success: true });
}

Response Examples

Different Response Types

// Different response types
export default async function(request, response) {
// JSON response
response.json({ message: 'Hello World' });

// HTML response
response.html('<h1>Hello World</h1>');

// Text response
response.text('Hello World');

// Status code chaining
response.status(201).json({ created: true });

// Custom headers
response.set('X-Custom-Header', 'value').json({ data: 'test' });

// Redirect
response.redirect('/login');

// Set cookies
response.cookie('session', 'abc123', { httpOnly: true }).json({ success: true });
}

Error Handling

// api/user/[id]/DELETE.js
export default async function(request, response) {
const { id } = request.params;

try {
const user = await getUserById(id);

if (!user) {
return response.status(404).json({
error: 'User not found',
code: 'USER_NOT_FOUND'
});
}

await deleteUser(id);

response.status(200).json({
message: 'User deleted successfully',
deletedAt: new Date().toISOString()
});
} catch (error) {
response.status(500).json({
error: 'Internal server error',
code: 'INTERNAL_ERROR'
});
}
}

Content Negotiation

// api/user/[id]/GET.js
export default async function(request, response) {
const { id } = request.params;
const userData = await getUserById(id);

// Check Accept header to determine response format
const acceptHeader = request.get('accept');

if (acceptHeader && acceptHeader.includes('text/html')) {
// Return HTML representation
response.html(`
<div>
<h1>${userData.name}</h1>
<p>Email: ${userData.email}</p>
</div>
`
);
} else {
// Default to JSON
response.json(userData);
}
}

Working with Cookies

// api/auth/login/POST.js
export default async function(request, response) {
const { username, password } = await request.json();

const user = await authenticateUser(username, password);

if (!user) {
return response.status(401).json({ error: 'Invalid credentials' });
}

// Set session cookie
const sessionToken = await createSessionToken(user.id);

response
.cookie('session', sessionToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000 // 24 hours
})
.json({
message: 'Login successful',
user: {
id: user.id,
username: user.username,
email: user.email
}
});
}

Advanced Request Handling

File Upload Handling

// api/upload/POST.js
export default async function(request, response) {
try {
// Get raw buffer for file upload
const buffer = await request.buffer();
const contentType = request.get('content-type');

// Save file to disk
const filename = `upload_${Date.now()}.${getExtensionFromMimeType(contentType)}`;
await fs.writeFile(`./uploads/${filename}`, buffer);

response.json({
message: 'File uploaded successfully',
filename: filename,
size: buffer.length
});
} catch (error) {
response.status(400).json({ error: 'Upload failed' });
}
}

Request Validation

// api/user/POST.js
export default async function(request, response) {
try {
const userData = await request.json();

// Validate required fields
const requiredFields = ['name', 'email', 'password'];
const missingFields = requiredFields.filter(field => !userData[field]);

if (missingFields.length > 0) {
return response.status(400).json({
error: 'Missing required fields',
missingFields
});
}

// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(userData.email)) {
return response.status(400).json({
error: 'Invalid email format'
});
}

// Create user
const newUser = await createUser(userData);

response.status(201).json({
message: 'User created successfully',
user: {
id: newUser.id,
name: newUser.name,
email: newUser.email
}
});
} catch (error) {
response.status(400).json({ error: 'Invalid request data' });
}
}