Request normalizes request access across runtimes and keeps handlers from depending directly on host-specific request primitives.
The Request class provides a generic wrapper for handling HTTP requests across different platforms with unified data access, cookie-backed session reads, and asynchronous body loading capabilities.
import { Request } from '@stackpress/ingest';
const req = new Request<ResourceType>({
url: 'http://example.com/api',
method: 'POST'
});- Properties
- Methods
- Data Access
- Request Creation
- Body Loading
- Platform Compatibility
- Type Parameters
- Examples
- Type Safety
The following properties are available when instantiating a Request.
| Property | Type | Description |
|---|---|---|
data |
CallableNest |
Combined data from query, post, and additional data |
headers |
CallableMap<string, string|string[]> |
Request headers |
query |
CallableNest |
URL query parameters |
post |
CallableNest |
POST body data |
session |
CallableSession |
Session data |
url |
URL |
Request URL object |
method |
Method |
HTTP method (GET, POST, PUT, DELETE, etc.) |
body |
Body|null |
Raw request body |
loaded |
boolean |
Whether the body has been loaded |
mimetype |
string |
Request body MIME type |
resource |
R |
Original request resource |
type |
string |
Type of body content |
loader |
RequestLoader<R> |
Body loader function |
The following methods are available when instantiating a Request.
The following example shows how to load the request body asynchronously for processing POST data and file uploads.
const req = new Request({
url: 'http://example.com/api',
method: 'POST'
});
await req.load(); // Loads body using the configured loader
console.log(req.body); // Access the loaded body
console.log(req.loaded); // true
console.log(req.post.get()); // Parsed POST body
console.log(req.data()); // Query + POST + additional data merged togetherReturns
The Request instance to allow method chaining.
In normal adapter-driven request handling you usually do not call load() yourself. Both the HTTP and WHATWG adapters call it before the route lifecycle begins so handlers can read req.post and req.data without needing to think about the host runtime.
The Request class provides multiple ways to access request data from different sources including query parameters, POST body, and session data.
These request data objects are all backed by the same nested callable data primitive. If you want the lower-level behavior behind req.query, req.post, and req.data, see Nest and Data Surfaces.
The data property combines query parameters, POST data, and additional context for unified access.
// URL: /users?page=1&limit=10
// POST body: { name: 'John', email: 'john@example.com' }
// Additional data: { userId: 123 }
const page = req.data('page'); // '1' (from query)
const name = req.data('name'); // 'John' (from POST)
const userId = req.data('userId'); // 123 (from additional data)
// Get all data
const allData = req.data();
// Returns: { page: '1', limit: '10', name: 'John', email: 'john@example.com', userId: 123 }Access URL query parameters directly for filtering and pagination.
// URL: /search?q=javascript&category=programming&page=2
const query = req.query.get('q'); // 'javascript'
const category = req.query.get('category'); // 'programming'
const page = req.query.get('page'); // '2'
// Get all query parameters
const allQuery = req.query.get();
// Returns: { q: 'javascript', category: 'programming', page: '2' }Access POST request body data after loading the request body.
// For POST requests with form data or JSON
await req.load(); // Load the body first
const name = req.post.get('name');
const email = req.post.get('email');
// Get all POST data
const allPost = req.post.get();Access request headers for authentication, content negotiation, and metadata.
const contentType = req.headers.get('content-type');
const authorization = req.headers.get('authorization');
const userAgent = req.headers.get('user-agent');
// Check if header exists
if (req.headers.has('x-api-key')) {
const apiKey = req.headers.get('x-api-key');
}
// Get all headers
const allHeaders = req.headers.entries();
for (const [name, value] of allHeaders) {
console.log(`${name}: ${value}`);
}Access and modify session data for user state management.
// Get session data
const userId = req.session.get('userId');
const username = req.session.get('username');
// Set session data
req.session.set('lastVisit', new Date().toISOString());
// Check if session has data
if (req.session.has('isAuthenticated')) {
// User is logged in
}
// Get all session data
const sessionData = req.session.get();On the request side, session data is usually derived from incoming cookies. That keeps route code focused on reading state while the response side owns cookie revisions and persistence.
The Request class supports various initialization patterns for different use cases and platforms.
Create a simple request with URL and method for basic HTTP operations.
import { Request } from '@stackpress/ingest';
const req = new Request({
url: 'http://example.com/api/users',
method: 'GET'
});Include custom headers for authentication and content negotiation.
const req = new Request({
url: 'http://example.com/api/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
}
});Initialize request with query parameters and POST data.
const req = new Request({
url: 'http://example.com/api/users',
method: 'POST',
data: {
name: 'John Doe',
email: 'john@example.com'
},
query: {
include: 'profile'
}
});Include session data for user context and state management.
const req = new Request({
url: 'http://example.com/api/profile',
method: 'GET',
session: {
userId: '123',
username: 'john',
role: 'admin'
}
});The Request class supports asynchronous body loading for different content types including JSON, form data, and file uploads.
Parsing is driven by the request content type. Ingest currently recognizes JSON, URL-encoded form data, and multipart form data. If a body uses another content type, the loader still caches the raw body string but req.post stays empty.
Handle JSON request bodies for API endpoints.
const req = new Request({
url: 'http://example.com/api/users',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John', email: 'john@example.com' })
});
await req.load();
console.log(req.mimetype); // 'application/json'
console.log(req.post.get()); // { name: 'John', email: 'john@example.com' }Process multipart form data for file uploads and complex forms.
const req = new Request({
url: 'http://example.com/api/upload',
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
// body would be set by the platform (browser FormData, etc.)
});
await req.load();
console.log(req.post.get('username'));
console.log(req.post.get('file')); // File dataHandle URL-encoded form submissions.
const req = new Request({
url: 'http://example.com/api/login',
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'username=john&password=secret'
});
await req.load();
console.log(req.post.get('username')); // 'john'
console.log(req.post.get('password')); // 'secret'The Request 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 { Request } from '@stackpress/ingest';
createServer((incomingMessage, serverResponse) => {
const req = new Request({ resource: incomingMessage });
console.log(req.method); // GET, POST, etc.
console.log(req.url.pathname); // /api/users
console.log(req.headers.get('user-agent'));
});Support for serverless environments like Vercel, Netlify, and Cloudflare Workers.
// Vercel, Netlify, etc.
export default async function handler(request: Request) {
const req = new Request({ resource: request });
console.log(req.method);
console.log(req.url.pathname);
console.log(req.headers.get('authorization'));
return new Response('OK');
}The Request class accepts one generic type parameter for type-safe resource handling.
| Parameter | Default | Description |
|---|---|---|
R |
any |
Request resource type (e.g., IncomingMessage, Request) |
import type { IncomingMessage } from 'node:http';
// Node.js HTTP request
const nodeReq = new Request<IncomingMessage>({
resource: incomingMessage
});
// WHATWG Fetch request
const fetchReq = new Request<globalThis.Request>({
resource: request
});
// Custom request type
interface CustomRequest {
customProperty: string;
}
const customReq = new Request<CustomRequest>({
resource: { customProperty: 'value' }
});The following examples demonstrate common Request usage patterns and best practices for real-world applications.
import { server } from '@stackpress/ingest/http';
const app = server();
app.post('/api/users', async ({ req, res }) => {
// Load request body
await req.load();
// Access different data sources
const userData = req.post.get(); // POST body data
const includeProfile = req.query.get('include'); // Query parameter
const currentUser = req.session.get('userId'); // Session data
// Validate required fields
if (!userData.name || !userData.email) {
res.setError('Name and email are required', {
name: !userData.name ? 'Name is required' : undefined,
email: !userData.email ? 'Email is required' : undefined
}, [], 400);
return;
}
// Create user
const newUser = {
id: Date.now(),
...userData,
createdBy: currentUser
};
res.setJSON({ user: newUser }, 201);
});app.on('request', async ({ req, res }) => {
// Skip authentication for public routes
if (req.url.pathname.startsWith('/public')) {
return true;
}
// Check for authorization header
const authHeader = req.headers.get('authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
res.setError('Authentication required', {}, [], 401);
return false;
}
// Extract and validate token
const token = authHeader.substring(7);
try {
const user = await validateToken(token);
// Store user in request data for later use
req.data.set('user', user);
req.session.set('userId', user.id);
return true; // Continue processing
} catch (error) {
res.setError('Invalid token', {}, [], 401);
return false;
}
}, 10); // High priority
async function validateToken(token: string) {
// Token validation logic
return { id: 1, username: 'john', role: 'admin' };
}app.post('/api/upload', async ({ req, res }) => {
await req.load();
// Check content type
if (!req.mimetype.startsWith('multipart/form-data')) {
res.setError('Multipart form data required', {}, [], 400);
return;
}
// Access uploaded files
const files = req.post.get('files');
const description = req.post.get('description');
if (!files || !Array.isArray(files)) {
res.setError('No files uploaded', {}, [], 400);
return;
}
// Process files
const uploadedFiles = [];
for (const file of files) {
const savedFile = await saveFile(file);
uploadedFiles.push(savedFile);
}
res.setJSON({
message: 'Files uploaded successfully',
files: uploadedFiles,
description
});
});The Request class supports TypeScript generics for type-safe resource handling:
import type { IncomingMessage } from 'node:http';
// Node.js HTTP request
const nodeReq = new Request<IncomingMessage>({
resource: incomingMessage
});
// WHATWG Fetch request
const fetchReq = new Request<globalThis.Request>({
resource: request
});
// Custom request type
interface CustomRequest {
customProperty: string;
}
const customReq = new Request<CustomRequest>({
resource: { customProperty: 'value' }
});The Request class provides a unified interface for handling HTTP requests across different platforms while maintaining type safety and providing convenient data access methods.