or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdisomorphic-functions.mdmiddleware.mdrequest-response.mdrpc-system.mdserver-functions.mdserver-utilities.mdssr-components.mdvite-plugin.md

request-response.mddocs/

0

# Request/Response Utilities

1

2

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.

3

4

## Capabilities

5

6

### Request Information Functions

7

8

Access information about the current HTTP request.

9

10

```typescript { .api }

11

/**

12

* Get the current request object

13

* @returns Current HTTP request

14

*/

15

function getRequest(): Request;

16

17

/**

18

* Get all request headers

19

* @returns Object containing all request headers

20

*/

21

function getRequestHeaders(): Record<string, string>;

22

23

/**

24

* Get a specific request header value

25

* @param name - Header name to retrieve

26

* @returns Header value or undefined

27

*/

28

function getRequestHeader(name: string): string | undefined;

29

30

/**

31

* Get the client IP address from the request

32

* @param options - Options for IP detection

33

* @returns Client IP address or undefined

34

*/

35

function getRequestIP(options?: { ipHeader?: string }): string | undefined;

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import {

42

getRequest,

43

getRequestHeaders,

44

getRequestHeader,

45

getRequestIP

46

} from "@tanstack/react-start";

47

48

// Access request information in a server function

49

const getUserInfo = createServerFn()

50

.handler(async () => {

51

const request = getRequest();

52

const headers = getRequestHeaders();

53

const userAgent = getRequestHeader("user-agent");

54

const clientIP = getRequestIP({ ipHeader: "x-forwarded-for" });

55

56

return {

57

method: request.method,

58

url: request.url,

59

userAgent,

60

clientIP,

61

headers

62

};

63

});

64

65

// Using request data for authentication

66

const authenticatedAction = createServerFn()

67

.handler(async () => {

68

const authHeader = getRequestHeader("authorization");

69

70

if (!authHeader || !authHeader.startsWith("Bearer ")) {

71

throw new Error("Authentication required");

72

}

73

74

const token = authHeader.substring(7);

75

// Verify token...

76

77

return { authenticated: true };

78

});

79

80

// Getting client information

81

const trackUserAction = createServerFn()

82

.handler(async (action: string) => {

83

const request = getRequest();

84

const userAgent = getRequestHeader("user-agent");

85

const clientIP = getRequestIP();

86

const referer = getRequestHeader("referer");

87

88

// Log the action with client information

89

console.log({

90

action,

91

userAgent,

92

clientIP,

93

referer,

94

timestamp: new Date().toISOString()

95

});

96

97

return { success: true };

98

});

99

```

100

101

### Response Utilities

102

103

Utilities for creating and manipulating HTTP responses.

104

105

```typescript { .api }

106

/**

107

* Create a JSON response with proper headers

108

* @param data - Data to serialize as JSON

109

* @param options - Response options

110

* @returns JSON response object

111

*/

112

function json<T>(

113

data: T,

114

options?: { status?: number; headers?: HeadersInit }

115

): JsonResponse;

116

117

/**

118

* Merge multiple header objects into one

119

* @param headers - Header objects to merge

120

* @returns Merged headers object

121

*/

122

function mergeHeaders(...headers: HeadersInit[]): Headers;

123

```

124

125

**Usage Examples:**

126

127

```typescript

128

import { json, mergeHeaders } from "@tanstack/react-start";

129

130

// Create JSON responses

131

const getUsers = createServerFn()

132

.handler(async () => {

133

const users = await db.user.findMany();

134

135

return json(users, {

136

status: 200,

137

headers: { "Cache-Control": "max-age=300" }

138

});

139

});

140

141

// Create responses with merged headers

142

const createUser = createServerFn()

143

.handler(async (userData) => {

144

const user = await db.user.create({ data: userData });

145

146

const responseHeaders = mergeHeaders(

147

{ "Content-Type": "application/json" },

148

{ "X-User-ID": user.id },

149

{ "Cache-Control": "no-cache" }

150

);

151

152

return json(user, {

153

status: 201,

154

headers: responseHeaders

155

});

156

});

157

158

// Error responses

159

const deleteUser = createServerFn()

160

.handler(async (userId: string) => {

161

const user = await db.user.findUnique({ where: { id: userId } });

162

163

if (!user) {

164

return json(

165

{ error: "User not found" },

166

{ status: 404 }

167

);

168

}

169

170

await db.user.delete({ where: { id: userId } });

171

172

return json({ success: true });

173

});

174

```

175

176

## Advanced Usage Patterns

177

178

### Request Body Processing

179

180

```typescript

181

import { getRequest } from "@tanstack/react-start";

182

183

const processFormData = createServerFn()

184

.handler(async () => {

185

const request = getRequest();

186

187

if (request.method !== "POST") {

188

return json({ error: "Method not allowed" }, { status: 405 });

189

}

190

191

const contentType = getRequestHeader("content-type");

192

193

if (contentType?.includes("application/json")) {

194

const jsonData = await request.json();

195

return json({ received: jsonData });

196

} else if (contentType?.includes("multipart/form-data")) {

197

const formData = await request.formData();

198

const data = Object.fromEntries(formData);

199

return json({ received: data });

200

}

201

202

return json({ error: "Unsupported content type" }, { status: 400 });

203

});

204

```

205

206

### CORS Handling

207

208

```typescript

209

import { mergeHeaders, json } from "@tanstack/react-start";

210

211

const corsEnabledApi = createServerFn()

212

.handler(async () => {

213

const origin = getRequestHeader("origin");

214

const allowedOrigins = ["https://example.com", "https://app.example.com"];

215

216

const corsHeaders = allowedOrigins.includes(origin)

217

? {

218

"Access-Control-Allow-Origin": origin,

219

"Access-Control-Allow-Credentials": "true"

220

}

221

: {};

222

223

const responseHeaders = mergeHeaders(

224

{ "Content-Type": "application/json" },

225

corsHeaders

226

);

227

228

return json(

229

{ message: "API response" },

230

{ headers: responseHeaders }

231

);

232

});

233

```

234

235

### Request Validation

236

237

```typescript

238

const validateApiKey = createServerFn()

239

.handler(async () => {

240

const apiKey = getRequestHeader("x-api-key");

241

const userAgent = getRequestHeader("user-agent");

242

const clientIP = getRequestIP();

243

244

if (!apiKey) {

245

return json(

246

{ error: "API key required" },

247

{ status: 401 }

248

);

249

}

250

251

// Rate limiting based on IP

252

const requestCount = await redis.get(`requests:${clientIP}`);

253

if (requestCount && parseInt(requestCount) > 100) {

254

return json(

255

{ error: "Rate limit exceeded" },

256

{ status: 429 }

257

);

258

}

259

260

// Validate API key

261

const isValid = await validateAPIKey(apiKey);

262

if (!isValid) {

263

return json(

264

{ error: "Invalid API key" },

265

{ status: 403 }

266

);

267

}

268

269

// Increment request count

270

await redis.incr(`requests:${clientIP}`);

271

await redis.expire(`requests:${clientIP}`, 3600);

272

273

return json({ success: true });

274

});

275

```

276

277

## Types

278

279

```typescript { .api }

280

// JSON response type

281

interface JsonResponse {

282

json(): any;

283

status: number;

284

headers: Headers;

285

ok: boolean;

286

statusText: string;

287

}

288

289

// Request IP options

290

interface RequestIPOptions {

291

ipHeader?: string;

292

}

293

```