Modern full-stack React framework with SSR, streaming, server functions, and API routes powered by TanStack Router and Vite.
—
TanStack Start provides utilities for accessing HTTP request information within server functions. These utilities give you access to request data, headers, and client information during server-side execution.
Access information about the current HTTP request.
/**
* Get the current request object
* @returns Current HTTP request
*/
function getRequest(): Request;
/**
* Get all request headers
* @returns Object containing all request headers
*/
function getRequestHeaders(): Record<string, string>;
/**
* Get a specific request header value
* @param name - Header name to retrieve
* @returns Header value or undefined
*/
function getRequestHeader(name: string): string | undefined;
/**
* Get the client IP address from the request
* @param options - Options for IP detection
* @returns Client IP address or undefined
*/
function getRequestIP(options?: { ipHeader?: string }): string | undefined;Usage Examples:
import {
getRequest,
getRequestHeaders,
getRequestHeader,
getRequestIP
} from "@tanstack/react-start";
// Access request information in a server function
const getUserInfo = createServerFn()
.handler(async () => {
const request = getRequest();
const headers = getRequestHeaders();
const userAgent = getRequestHeader("user-agent");
const clientIP = getRequestIP({ ipHeader: "x-forwarded-for" });
return {
method: request.method,
url: request.url,
userAgent,
clientIP,
headers
};
});
// Using request data for authentication
const authenticatedAction = createServerFn()
.handler(async () => {
const authHeader = getRequestHeader("authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
throw new Error("Authentication required");
}
const token = authHeader.substring(7);
// Verify token...
return { authenticated: true };
});
// Getting client information
const trackUserAction = createServerFn()
.handler(async (action: string) => {
const request = getRequest();
const userAgent = getRequestHeader("user-agent");
const clientIP = getRequestIP();
const referer = getRequestHeader("referer");
// Log the action with client information
console.log({
action,
userAgent,
clientIP,
referer,
timestamp: new Date().toISOString()
});
return { success: true };
});Utilities for creating and manipulating HTTP responses.
/**
* Create a JSON response with proper headers
* @param data - Data to serialize as JSON
* @param options - Response options
* @returns JSON response object
*/
function json<T>(
data: T,
options?: { status?: number; headers?: HeadersInit }
): JsonResponse;
/**
* Merge multiple header objects into one
* @param headers - Header objects to merge
* @returns Merged headers object
*/
function mergeHeaders(...headers: HeadersInit[]): Headers;Usage Examples:
import { json, mergeHeaders } from "@tanstack/react-start";
// Create JSON responses
const getUsers = createServerFn()
.handler(async () => {
const users = await db.user.findMany();
return json(users, {
status: 200,
headers: { "Cache-Control": "max-age=300" }
});
});
// Create responses with merged headers
const createUser = createServerFn()
.handler(async (userData) => {
const user = await db.user.create({ data: userData });
const responseHeaders = mergeHeaders(
{ "Content-Type": "application/json" },
{ "X-User-ID": user.id },
{ "Cache-Control": "no-cache" }
);
return json(user, {
status: 201,
headers: responseHeaders
});
});
// Error responses
const deleteUser = createServerFn()
.handler(async (userId: string) => {
const user = await db.user.findUnique({ where: { id: userId } });
if (!user) {
return json(
{ error: "User not found" },
{ status: 404 }
);
}
await db.user.delete({ where: { id: userId } });
return json({ success: true });
});import { getRequest } from "@tanstack/react-start";
const processFormData = createServerFn()
.handler(async () => {
const request = getRequest();
if (request.method !== "POST") {
return json({ error: "Method not allowed" }, { status: 405 });
}
const contentType = getRequestHeader("content-type");
if (contentType?.includes("application/json")) {
const jsonData = await request.json();
return json({ received: jsonData });
} else if (contentType?.includes("multipart/form-data")) {
const formData = await request.formData();
const data = Object.fromEntries(formData);
return json({ received: data });
}
return json({ error: "Unsupported content type" }, { status: 400 });
});import { mergeHeaders, json } from "@tanstack/react-start";
const corsEnabledApi = createServerFn()
.handler(async () => {
const origin = getRequestHeader("origin");
const allowedOrigins = ["https://example.com", "https://app.example.com"];
const corsHeaders = allowedOrigins.includes(origin)
? {
"Access-Control-Allow-Origin": origin,
"Access-Control-Allow-Credentials": "true"
}
: {};
const responseHeaders = mergeHeaders(
{ "Content-Type": "application/json" },
corsHeaders
);
return json(
{ message: "API response" },
{ headers: responseHeaders }
);
});const validateApiKey = createServerFn()
.handler(async () => {
const apiKey = getRequestHeader("x-api-key");
const userAgent = getRequestHeader("user-agent");
const clientIP = getRequestIP();
if (!apiKey) {
return json(
{ error: "API key required" },
{ status: 401 }
);
}
// Rate limiting based on IP
const requestCount = await redis.get(`requests:${clientIP}`);
if (requestCount && parseInt(requestCount) > 100) {
return json(
{ error: "Rate limit exceeded" },
{ status: 429 }
);
}
// Validate API key
const isValid = await validateAPIKey(apiKey);
if (!isValid) {
return json(
{ error: "Invalid API key" },
{ status: 403 }
);
}
// Increment request count
await redis.incr(`requests:${clientIP}`);
await redis.expire(`requests:${clientIP}`, 3600);
return json({ success: true });
});// JSON response type
interface JsonResponse {
json(): any;
status: number;
headers: Headers;
ok: boolean;
statusText: string;
}
// Request IP options
interface RequestIPOptions {
ipHeader?: string;
}Install with Tessl CLI
npx tessl i tessl/npm-tanstack--react-start