Response gives handlers and hooks one consistent output model across runtimes.
The Response class provides a generic wrapper for handling HTTP responses across different platforms with support for multiple response types, header management, session revisions, and adapter-aware dispatch.
Like the request object, response-side nested data objects such as data and errors build on the same underlying nested callable primitive. See Nest and Data Surfaces for the shared model.
import { Response } from '@stackpress/ingest';
const res = new Response<ResourceType>({
headers: { 'Content-Type': 'application/json' }
});- Properties
- Methods
- Header Management
- Session Management
- Response Creation
- Platform Compatibility
- Type Parameters
- Examples
- Type Safety
The following properties are available when instantiating a Response.
| Property | Type | Description |
|---|---|---|
headers |
CallableMap<string, string|string[]> |
Response headers |
session |
CallableSession |
Session data |
errors |
CallableNest |
Validation errors |
data |
CallableNest |
Response data that can carry response-side metadata separate from body/results |
body |
Body|null |
Response body |
code |
number |
HTTP status code |
error |
string|undefined |
Error message |
redirected |
boolean |
Whether response is a redirect |
sent |
boolean |
Whether response has been sent |
stack |
Trace[]|undefined |
Stack trace for errors |
status |
string |
HTTP status message |
total |
number |
Total count of results |
mimetype |
string|undefined |
Response MIME type |
resource |
S |
Original response resource |
type |
string |
Type of body content |
dispatcher |
ResponseDispatcher<S> |
Response dispatcher function |
The following methods are available when instantiating a Response.
The following example shows how to set a JSON response for API endpoints.
// Simple JSON response
res.setJSON({ message: 'Success', data: results });
// JSON response with custom status
res.setJSON({ user: userData }, 201, 'Created');
// JSON string response
res.setJSON('{"message": "Success"}', 200, 'OK');Parameters
| Parameter | Type | Description |
|---|---|---|
body |
string|NestedObject |
JSON data or string |
code |
number |
HTTP status code (default: 200) |
status |
string |
HTTP status message (optional) |
Returns
The Response instance to allow method chaining.
The following example shows how to set an HTML response for web pages.
// Simple HTML response
res.setHTML('<h1>Welcome</h1>');
// HTML response with custom status
res.setHTML('<h1>Page Not Found</h1>', 404, 'Not Found');
// HTML response with template
const html = `
<html>
<head><title>User Profile</title></head>
<body><h1>Welcome, ${user.name}!</h1></body>
</html>
`;
res.setHTML(html, 200, 'OK');Parameters
| Parameter | Type | Description |
|---|---|---|
body |
string |
HTML content |
code |
number |
HTTP status code (default: 200) |
status |
string |
HTTP status message (optional) |
Returns
The Response instance to allow method chaining.
The following example shows how to set an error response with validation details.
// Simple error
res.setError('Invalid input', {}, [], 400, 'Bad Request');
// Error with validation details
res.setError('Validation failed', {
name: 'Name is required',
email: 'Invalid email format'
}, [], 400);
// Error with stack trace
res.setError('Database error', {}, stackTrace, 500, 'Internal Server Error');
// Error from response object
res.setError({
code: 404,
error: 'User not found',
errors: { id: 'User ID does not exist' }
});Parameters
| Parameter | Type | Description |
|---|---|---|
error |
string|ErrorResponse |
Error message or response object |
errors |
NestedObject<string|string[]> |
Validation errors (default: {}) |
stack |
Trace[] |
Stack trace (default: []) |
code |
number |
HTTP status code (default: 400) |
status |
string |
HTTP status message (optional) |
Returns
The Response instance to allow method chaining.
The following example shows how to set a single result response.
// Single result
res.setResults({ id: 1, name: 'John Doe' });
// Result with custom status
res.setResults({ user: newUser }, 201, 'Created');
// Complex result object
res.setResults({
user: userData,
permissions: userPermissions,
settings: userSettings
});Parameters
| Parameter | Type | Description |
|---|---|---|
body |
NestedObject |
Result object |
code |
number |
HTTP status code (default: 200) |
status |
string |
HTTP status message (optional) |
Returns
The Response instance to allow method chaining.
When the body is a plain object or array, the adapters serialize it as a structured JSON payload rather than writing the raw value directly. That is why helpers such as setResults() and setRows() fit naturally with the rest of the response model.
res.data() is useful when a route or hook needs to carry extra response-side state without mixing it into the real result set. Template engines can read from it, for example, while setResults() continues to describe the actual payload:
if (res.code === 200) {
res.data.set('sessionId', 'abc123');
res.data.set('sessionUser', 'John Doe');
}
res.setResults(results);The following example shows how to set a collection response with total count for pagination.
// Collection with total count
res.setRows([
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' }
], 100); // 2 items out of 100 total
// Collection without total
res.setRows(users);
// Empty collection
res.setRows([], 0);Parameters
| Parameter | Type | Description |
|---|---|---|
body |
NestedObject[] |
Array of result objects |
total |
number |
Total count of possible results (default: 0) |
code |
number |
HTTP status code (default: 200) |
status |
string |
HTTP status message (optional) |
Returns
The Response instance to allow method chaining.
The following example shows how to redirect the response to another URL.
// Simple redirect
res.redirect('/login');
// Redirect with custom status
res.redirect('/dashboard', 301, 'Moved Permanently');
// External redirect
res.redirect('https://example.com', 302, 'Found');
// Conditional redirect
if (!user.isAuthenticated) {
res.redirect('/login', 302, 'Found');
return;
}Parameters
| Parameter | Type | Description |
|---|---|---|
url |
string |
Redirect URL |
code |
number |
HTTP status code (default: 302) |
status |
string |
HTTP status message (optional) |
Returns
The Response instance to allow method chaining.
The following example shows how to dispatch the response to the native resource.
// Dispatch to native response
const nativeResponse = await res.dispatch();
// Use in route handler
app.get('/api/users', async ({ res }) => {
res.setJSON({ users: [] });
return await res.dispatch(); // Send response
});Dispatch is where the runtime adapter turns the response model into a real platform response. In practice that means:
- strings, buffers, and
Uint8Arrayvalues are written directly - objects and arrays become structured JSON payloads
- Node
Readablestreams and webReadableStreamvalues are streamed - redirects and headers are applied before the body is written
- session revisions become
Set-Cookieheaders
This matters because handlers can stay focused on setting intent while the adapter handles the platform-specific write path.
import fs from 'node:fs';
app.get('/icon.png', ({ res }) => {
res.setBody('image/png', fs.createReadStream('./icon.png'));
});
app.get('/events', ({ res }) => {
res.headers
.set('Cache-Control', 'no-cache')
.set('Connection', 'keep-alive');
res.setBody('text/event-stream', new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode('data: hello\\r\\n\\r\\n'));
}
}));
});In WHATWG runtimes a route can also provide an already-built native response resource. The WHATWG adapter will return that resource directly instead of rebuilding it.
Returns
The native response resource after dispatching.
The following example shows how to convert the response to a status response object.
const statusResponse = res.toStatusResponse();
console.log(statusResponse);
// Returns: { code, status, error, errors, stack, results, total }
// Use for API responses
const apiResponse = res.toStatusResponse();
return {
statusCode: apiResponse.code,
body: JSON.stringify(apiResponse)
};Returns
A StatusResponse object with all response details.
The Response class provides comprehensive header management for HTTP responses including CORS, security, and caching headers.
Control response headers for content negotiation and security.
// Set individual headers
res.headers.set('Content-Type', 'application/json');
res.headers.set('Cache-Control', 'no-cache');
res.headers.set('X-API-Version', '1.0');
// Set multiple values for same header
res.headers.set('Set-Cookie', ['session=abc123', 'csrf=xyz789']);
// Set headers during response creation
const res = new Response({
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});Access and inspect response headers.
const contentType = res.headers.get('content-type');
const cookies = res.headers.get('set-cookie'); // Array if multiple values
// Check if header exists
if (res.headers.has('authorization')) {
// Header is set
}
// Get all headers
for (const [name, value] of res.headers.entries()) {
console.log(`${name}: ${value}`);
}Set frequently used headers for web applications.
// CORS headers
res.headers.set('Access-Control-Allow-Origin', '*');
res.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// Security headers
res.headers.set('X-Content-Type-Options', 'nosniff');
res.headers.set('X-Frame-Options', 'DENY');
res.headers.set('X-XSS-Protection', '1; mode=block');
// Caching headers
res.headers.set('Cache-Control', 'public, max-age=3600');
res.headers.set('ETag', '"abc123"');
res.headers.set('Last-Modified', new Date().toUTCString());The Response class integrates with session management for user state persistence.
Store user data in the session for subsequent requests.
// Set session values
res.session.set('userId', user.id);
res.session.set('username', user.username);
res.session.set('lastLogin', new Date().toISOString());
// Set multiple session values
res.session.set({
userId: user.id,
role: user.role,
permissions: user.permissions
});Access session data for user context.
const userId = res.session.get('userId');
const username = res.session.get('username');
// Get all session data
const sessionData = res.session.get();Manage session cookies with security options.
// Session cookies are automatically managed
// but you can customize them
res.headers.set('Set-Cookie', [
'session=abc123; HttpOnly; Secure; SameSite=Strict',
'csrf=xyz789; HttpOnly; Secure'
]);The Response class supports various initialization patterns for different use cases.
Create a simple response for basic HTTP operations.
import { Response } from '@stackpress/ingest';
const res = new Response();Initialize response with custom headers.
const res = new Response({
headers: {
'Content-Type': 'application/json',
'X-API-Version': '1.0'
}
});Initialize response with default data.
const res = new Response({
data: {
timestamp: Date.now(),
version: '1.0.0'
}
});Initialize response with platform-specific resource.
import type { ServerResponse } from 'node:http';
const res = new Response<ServerResponse>({
resource: serverResponse
});The Response class provides cross-platform compatibility for Node.js HTTP and WHATWG Fetch environments.
Integration with Node.js HTTP server for traditional server applications.
import { createServer } from 'node:http';
import { Response } from '@stackpress/ingest';
createServer((req, serverResponse) => {
const res = new Response({ resource: serverResponse });
res.setJSON({ message: 'Hello from Node.js' });
res.dispatch(); // Sends response
});Support for serverless environments like Vercel, Netlify, and Cloudflare Workers.
// Vercel, Netlify, etc.
export default async function handler(request: Request) {
const res = new Response();
res.setJSON({ message: 'Hello from serverless' });
return await res.dispatch(); // Returns Response object
}The Response class accepts one generic type parameter for type-safe resource handling.
| Parameter | Default | Description |
|---|---|---|
S |
any |
Response resource type (e.g., ServerResponse, Response) |
import type { ServerResponse } from 'node:http';
// Node.js HTTP response
const nodeRes = new Response<ServerResponse>({
resource: serverResponse
});
// WHATWG Fetch response
const fetchRes = new Response<globalThis.Response>();
// Custom response type
interface CustomResponse {
customProperty: string;
}
const customRes = new Response<CustomResponse>({
resource: { customProperty: 'value' }
});The following examples demonstrate common Response usage patterns and best practices for real-world applications.
import { server } from '@stackpress/ingest/http';
const app = server();
app.get('/api/users/:id', async ({ req, res }) => {
const userId = req.data('id');
try {
const user = await getUserById(userId);
if (!user) {
res.setError('User not found', { id: 'User does not exist' }, [], 404);
return;
}
// Set cache headers
res.headers.set('Cache-Control', 'public, max-age=300');
res.headers.set('ETag', `"user-${user.id}-${user.updatedAt}"`);
res.setResults(user);
} catch (error) {
res.setError('Database error', {}, [], 500);
}
});
async function getUserById(id: string) {
// Database lookup logic
return { id, name: 'John Doe', updatedAt: Date.now() };
}app.get('/api/users', async ({ req, res }) => {
const page = parseInt(req.query.get('page') || '1');
const limit = parseInt(req.query.get('limit') || '10');
const offset = (page - 1) * limit;
try {
const { users, total } = await getUsersPaginated(limit, offset);
// Set pagination headers
res.headers.set('X-Total-Count', total.toString());
res.headers.set('X-Page', page.toString());
res.headers.set('X-Per-Page', limit.toString());
// Add pagination links
const baseUrl = `${req.url.origin}${req.url.pathname}`;
const links = [];
if (page > 1) {
links.push(`<${baseUrl}?page=${page - 1}&limit=${limit}>; rel="prev"`);
}
if (offset + limit < total) {
links.push(`<${baseUrl}?page=${page + 1}&limit=${limit}>; rel="next"`);
}
if (links.length > 0) {
res.headers.set('Link', links.join(', '));
}
res.setRows(users, total);
} catch (error) {
res.setError('Failed to fetch users', {}, [], 500);
}
});app.get('/api/files/:id/download', async ({ req, res }) => {
const fileId = req.data('id');
try {
const file = await getFileById(fileId);
if (!file) {
res.setError('File not found', {}, [], 404);
return;
}
// Set download headers
res.headers.set('Content-Type', file.mimetype);
res.headers.set('Content-Length', file.size.toString());
res.headers.set('Content-Disposition', `attachment; filename="${file.name}"`);
// Stream file content
res.body = file.stream;
res.code = 200;
res.status = 'OK';
await res.dispatch();
} catch (error) {
res.setError('Failed to download file', {}, [], 500);
}
});app.post('/api/auth/login', async ({ req, res }) => {
await req.load();
const { username, password } = req.data();
try {
const user = await authenticateUser(username, password);
if (!user) {
res.setError('Invalid credentials', {
username: 'Invalid username or password'
}, [], 401);
return;
}
// Generate token
const token = await generateToken(user);
// Set session
res.session.set('userId', user.id);
res.session.set('username', user.username);
// Set secure cookie
res.headers.set('Set-Cookie', [
`token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=86400`,
`user=${user.username}; Secure; SameSite=Strict; Max-Age=86400`
]);
res.setResults({
user: {
id: user.id,
username: user.username,
role: user.role
},
token,
expiresIn: 86400
});
} catch (error) {
res.setError('Authentication failed', {}, [], 500);
}
});app.on('error', (error, req, res) => {
console.error('Global error:', error);
if (!res.sent) {
if (error instanceof ValidationError) {
res.setError('Validation failed', error.errors, [], 400);
} else if (error instanceof AuthenticationError) {
res.setError('Authentication required', {}, [], 401);
} else if (error instanceof AuthorizationError) {
res.setError('Access denied', {}, [], 403);
} else {
// Log detailed error but don't expose to client
res.setError('Internal server error', {}, [], 500);
}
}
});The Response class supports TypeScript generics for type-safe resource handling:
import type { ServerResponse } from 'node:http';
// Node.js HTTP response
const nodeRes = new Response<ServerResponse>({
resource: serverResponse
});
// WHATWG Fetch response
const fetchRes = new Response<globalThis.Response>();
// Custom response type
interface CustomResponse {
customProperty: string;
}
const customRes = new Response<CustomResponse>({
resource: { customProperty: 'value' }
});The Response class provides a unified interface for handling HTTP responses across different platforms while maintaining type safety and providing convenient response formatting methods.