npm-tanstack--react-start

Description
Modern full-stack React framework with SSR, streaming, server functions, and API routes powered by TanStack Router and Vite.
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-tanstack--react-start@1.132.0

request-response.md docs/

1
# Request/Response Utilities
2
3
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.
4
5
## Capabilities
6
7
### Request Information Functions
8
9
Access information about the current HTTP request.
10
11
```typescript { .api }
12
/**
13
* Get the current request object
14
* @returns Current HTTP request
15
*/
16
function getRequest(): Request;
17
18
/**
19
* Get all request headers
20
* @returns Object containing all request headers
21
*/
22
function getRequestHeaders(): Record<string, string>;
23
24
/**
25
* Get a specific request header value
26
* @param name - Header name to retrieve
27
* @returns Header value or undefined
28
*/
29
function getRequestHeader(name: string): string | undefined;
30
31
/**
32
* Get the client IP address from the request
33
* @param options - Options for IP detection
34
* @returns Client IP address or undefined
35
*/
36
function getRequestIP(options?: { ipHeader?: string }): string | undefined;
37
```
38
39
**Usage Examples:**
40
41
```typescript
42
import {
43
getRequest,
44
getRequestHeaders,
45
getRequestHeader,
46
getRequestIP
47
} from "@tanstack/react-start";
48
49
// Access request information in a server function
50
const getUserInfo = createServerFn()
51
.handler(async () => {
52
const request = getRequest();
53
const headers = getRequestHeaders();
54
const userAgent = getRequestHeader("user-agent");
55
const clientIP = getRequestIP({ ipHeader: "x-forwarded-for" });
56
57
return {
58
method: request.method,
59
url: request.url,
60
userAgent,
61
clientIP,
62
headers
63
};
64
});
65
66
// Using request data for authentication
67
const authenticatedAction = createServerFn()
68
.handler(async () => {
69
const authHeader = getRequestHeader("authorization");
70
71
if (!authHeader || !authHeader.startsWith("Bearer ")) {
72
throw new Error("Authentication required");
73
}
74
75
const token = authHeader.substring(7);
76
// Verify token...
77
78
return { authenticated: true };
79
});
80
81
// Getting client information
82
const trackUserAction = createServerFn()
83
.handler(async (action: string) => {
84
const request = getRequest();
85
const userAgent = getRequestHeader("user-agent");
86
const clientIP = getRequestIP();
87
const referer = getRequestHeader("referer");
88
89
// Log the action with client information
90
console.log({
91
action,
92
userAgent,
93
clientIP,
94
referer,
95
timestamp: new Date().toISOString()
96
});
97
98
return { success: true };
99
});
100
```
101
102
### Response Utilities
103
104
Utilities for creating and manipulating HTTP responses.
105
106
```typescript { .api }
107
/**
108
* Create a JSON response with proper headers
109
* @param data - Data to serialize as JSON
110
* @param options - Response options
111
* @returns JSON response object
112
*/
113
function json<T>(
114
data: T,
115
options?: { status?: number; headers?: HeadersInit }
116
): JsonResponse;
117
118
/**
119
* Merge multiple header objects into one
120
* @param headers - Header objects to merge
121
* @returns Merged headers object
122
*/
123
function mergeHeaders(...headers: HeadersInit[]): Headers;
124
```
125
126
**Usage Examples:**
127
128
```typescript
129
import { json, mergeHeaders } from "@tanstack/react-start";
130
131
// Create JSON responses
132
const getUsers = createServerFn()
133
.handler(async () => {
134
const users = await db.user.findMany();
135
136
return json(users, {
137
status: 200,
138
headers: { "Cache-Control": "max-age=300" }
139
});
140
});
141
142
// Create responses with merged headers
143
const createUser = createServerFn()
144
.handler(async (userData) => {
145
const user = await db.user.create({ data: userData });
146
147
const responseHeaders = mergeHeaders(
148
{ "Content-Type": "application/json" },
149
{ "X-User-ID": user.id },
150
{ "Cache-Control": "no-cache" }
151
);
152
153
return json(user, {
154
status: 201,
155
headers: responseHeaders
156
});
157
});
158
159
// Error responses
160
const deleteUser = createServerFn()
161
.handler(async (userId: string) => {
162
const user = await db.user.findUnique({ where: { id: userId } });
163
164
if (!user) {
165
return json(
166
{ error: "User not found" },
167
{ status: 404 }
168
);
169
}
170
171
await db.user.delete({ where: { id: userId } });
172
173
return json({ success: true });
174
});
175
```
176
177
## Advanced Usage Patterns
178
179
### Request Body Processing
180
181
```typescript
182
import { getRequest } from "@tanstack/react-start";
183
184
const processFormData = createServerFn()
185
.handler(async () => {
186
const request = getRequest();
187
188
if (request.method !== "POST") {
189
return json({ error: "Method not allowed" }, { status: 405 });
190
}
191
192
const contentType = getRequestHeader("content-type");
193
194
if (contentType?.includes("application/json")) {
195
const jsonData = await request.json();
196
return json({ received: jsonData });
197
} else if (contentType?.includes("multipart/form-data")) {
198
const formData = await request.formData();
199
const data = Object.fromEntries(formData);
200
return json({ received: data });
201
}
202
203
return json({ error: "Unsupported content type" }, { status: 400 });
204
});
205
```
206
207
### CORS Handling
208
209
```typescript
210
import { mergeHeaders, json } from "@tanstack/react-start";
211
212
const corsEnabledApi = createServerFn()
213
.handler(async () => {
214
const origin = getRequestHeader("origin");
215
const allowedOrigins = ["https://example.com", "https://app.example.com"];
216
217
const corsHeaders = allowedOrigins.includes(origin)
218
? {
219
"Access-Control-Allow-Origin": origin,
220
"Access-Control-Allow-Credentials": "true"
221
}
222
: {};
223
224
const responseHeaders = mergeHeaders(
225
{ "Content-Type": "application/json" },
226
corsHeaders
227
);
228
229
return json(
230
{ message: "API response" },
231
{ headers: responseHeaders }
232
);
233
});
234
```
235
236
### Request Validation
237
238
```typescript
239
const validateApiKey = createServerFn()
240
.handler(async () => {
241
const apiKey = getRequestHeader("x-api-key");
242
const userAgent = getRequestHeader("user-agent");
243
const clientIP = getRequestIP();
244
245
if (!apiKey) {
246
return json(
247
{ error: "API key required" },
248
{ status: 401 }
249
);
250
}
251
252
// Rate limiting based on IP
253
const requestCount = await redis.get(`requests:${clientIP}`);
254
if (requestCount && parseInt(requestCount) > 100) {
255
return json(
256
{ error: "Rate limit exceeded" },
257
{ status: 429 }
258
);
259
}
260
261
// Validate API key
262
const isValid = await validateAPIKey(apiKey);
263
if (!isValid) {
264
return json(
265
{ error: "Invalid API key" },
266
{ status: 403 }
267
);
268
}
269
270
// Increment request count
271
await redis.incr(`requests:${clientIP}`);
272
await redis.expire(`requests:${clientIP}`, 3600);
273
274
return json({ success: true });
275
});
276
```
277
278
## Types
279
280
```typescript { .api }
281
// JSON response type
282
interface JsonResponse {
283
json(): any;
284
status: number;
285
headers: Headers;
286
ok: boolean;
287
statusText: string;
288
}
289
290
// Request IP options
291
interface RequestIPOptions {
292
ipHeader?: string;
293
}
294
```