or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-responses.mdapi-routing.mdbackground-tasks.mdcore-application.mddata-utilities.mddependency-injection.mdexception-handling.mdindex.mdmiddleware.mdrequest-parameters.mdrequest-response.mdsecurity-authentication.mdstatic-templating.mdtesting.mdwebsocket-support.md

request-response.mddocs/

0

# Request and Response Handling

1

2

FastAPI provides comprehensive request and response handling through Starlette's Request and Response objects, along with FastAPI-specific enhancements like UploadFile for file handling and various response classes for different content types.

3

4

## Capabilities

5

6

### Request Object

7

8

HTTP request object providing access to all request data including headers, cookies, query parameters, form data, and JSON body.

9

10

```python { .api }

11

class Request:

12

"""

13

Starlette Request object with all HTTP request functionality.

14

15

Key attributes and methods for accessing request data:

16

"""

17

18

# Request metadata

19

method: str # HTTP method (GET, POST, etc.)

20

url: URL # Complete URL object

21

headers: Headers # HTTP headers

22

query_params: QueryParams # Query string parameters

23

path_params: dict # Path parameters from URL

24

cookies: dict # HTTP cookies

25

client: Address # Client connection info

26

27

# Request body access

28

async def body(self) -> bytes:

29

"""Get raw request body as bytes."""

30

pass

31

32

async def json(self) -> Any:

33

"""Parse request body as JSON."""

34

pass

35

36

async def form(self) -> FormData:

37

"""Parse request body as form data."""

38

pass

39

40

# State and context

41

state: State # Request-scoped state storage

42

scope: dict # ASGI scope dictionary

43

44

# Utility methods

45

def url_for(self, name: str, **path_params) -> str:

46

"""Generate URL for named route."""

47

pass

48

```

49

50

### Response Classes

51

52

Base response class and specialized response classes for different content types and use cases.

53

54

```python { .api }

55

class Response:

56

def __init__(

57

self,

58

content: Any = None,

59

status_code: int = 200,

60

headers: dict = None,

61

media_type: str = None,

62

background: BackgroundTask = None,

63

) -> None:

64

"""

65

Base HTTP response class.

66

67

Parameters:

68

- content: Response content (string, bytes, or None)

69

- status_code: HTTP status code

70

- headers: Additional HTTP headers

71

- media_type: Content-Type header value

72

- background: Background task to run after response

73

"""

74

75

# Response properties

76

status_code: int # HTTP status code

77

headers: Headers # Response headers

78

media_type: str # Content-Type

79

body: bytes # Response body

80

background: BackgroundTask # Background task

81

82

class JSONResponse(Response):

83

def __init__(

84

self,

85

content: Any = None,

86

status_code: int = 200,

87

headers: dict = None,

88

media_type: str = "application/json",

89

background: BackgroundTask = None,

90

) -> None:

91

"""

92

JSON response with automatic serialization.

93

94

Parameters:

95

- content: Python object to serialize as JSON

96

- Other parameters same as Response

97

"""

98

99

class HTMLResponse(Response):

100

def __init__(

101

self,

102

content: str = None,

103

status_code: int = 200,

104

headers: dict = None,

105

media_type: str = "text/html",

106

background: BackgroundTask = None,

107

) -> None:

108

"""HTML response for returning HTML content."""

109

110

class PlainTextResponse(Response):

111

def __init__(

112

self,

113

content: str = None,

114

status_code: int = 200,

115

headers: dict = None,

116

media_type: str = "text/plain",

117

background: BackgroundTask = None,

118

) -> None:

119

"""Plain text response."""

120

121

class RedirectResponse(Response):

122

def __init__(

123

self,

124

url: str,

125

status_code: int = 307,

126

headers: dict = None,

127

background: BackgroundTask = None,

128

) -> None:

129

"""

130

HTTP redirect response.

131

132

Parameters:

133

- url: Target URL for redirection

134

- status_code: Redirect status code (307, 302, 301, etc.)

135

"""

136

137

class FileResponse(Response):

138

def __init__(

139

self,

140

path: str = None,

141

status_code: int = 200,

142

headers: dict = None,

143

media_type: str = None,

144

background: BackgroundTask = None,

145

filename: str = None,

146

stat_result: os.stat_result = None,

147

method: str = None,

148

) -> None:

149

"""

150

File download response.

151

152

Parameters:

153

- path: File system path to serve

154

- filename: Filename for Content-Disposition header

155

- stat_result: Cached file stat result for performance

156

- method: HTTP method for conditional logic

157

"""

158

159

class StreamingResponse(Response):

160

def __init__(

161

self,

162

content: Any,

163

status_code: int = 200,

164

headers: dict = None,

165

media_type: str = None,

166

background: BackgroundTask = None,

167

) -> None:

168

"""

169

Streaming response for large data or real-time content.

170

171

Parameters:

172

- content: Iterable or async iterable of bytes/strings

173

- Other parameters same as Response

174

"""

175

```

176

177

### FastAPI-Specific Response Classes

178

179

Enhanced JSON response classes using high-performance JSON libraries.

180

181

```python { .api }

182

class UJSONResponse(JSONResponse):

183

def render(self, content: Any) -> bytes:

184

"""

185

Ultra-fast JSON response using ujson library.

186

187

Requires: pip install ujson

188

Provides faster JSON serialization than standard library.

189

"""

190

191

class ORJSONResponse(JSONResponse):

192

def render(self, content: Any) -> bytes:

193

"""

194

Fast JSON response using orjson library.

195

196

Requires: pip install orjson

197

Fastest JSON serialization with additional features.

198

"""

199

```

200

201

### File Upload Handling

202

203

UploadFile class for handling multipart file uploads with async file operations.

204

205

```python { .api }

206

class UploadFile:

207

def __init__(

208

self,

209

file: BinaryIO,

210

*,

211

size: int = None,

212

filename: str = None,

213

headers: Headers = None,

214

) -> None: ...

215

216

# File metadata

217

filename: Optional[str] # Original filename

218

content_type: Optional[str] # MIME content type

219

headers: Headers # File-specific headers

220

size: Optional[int] # File size in bytes

221

file: BinaryIO # Underlying file object

222

223

# Async file operations

224

async def read(self, size: int = -1) -> bytes:

225

"""Read data from uploaded file."""

226

227

async def readline(self, size: int = -1) -> bytes:

228

"""Read a line from uploaded file."""

229

230

async def readlines(self) -> List[bytes]:

231

"""Read all lines from uploaded file."""

232

233

async def write(self, data: bytes) -> None:

234

"""Write data to uploaded file."""

235

236

async def seek(self, offset: int) -> None:

237

"""Seek to position in uploaded file."""

238

239

async def close(self) -> None:

240

"""Close the uploaded file."""

241

```

242

243

## Usage Examples

244

245

### Accessing Request Data

246

247

```python

248

from fastapi import FastAPI, Request

249

250

app = FastAPI()

251

252

@app.post("/analyze-request")

253

async def analyze_request(request: Request):

254

return {

255

"method": request.method,

256

"url": str(request.url),

257

"headers": dict(request.headers),

258

"query_params": dict(request.query_params),

259

"path_params": request.path_params,

260

"cookies": request.cookies,

261

"client": f"{request.client.host}:{request.client.port}",

262

"body": (await request.body()).decode()

263

}

264

265

@app.get("/items/{item_id}")

266

async def get_item(item_id: int, request: Request):

267

# Access path parameters

268

path_params = request.path_params

269

270

# Access query parameters

271

query_params = request.query_params

272

273

# Access headers

274

user_agent = request.headers.get("user-agent")

275

276

return {

277

"item_id": item_id,

278

"path_params": path_params,

279

"query_params": dict(query_params),

280

"user_agent": user_agent

281

}

282

```

283

284

### Custom Response Types

285

286

```python

287

from fastapi import FastAPI

288

from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse

289

290

app = FastAPI()

291

292

@app.get("/html", response_class=HTMLResponse)

293

def get_html():

294

html_content = """

295

<html>

296

<head><title>FastAPI HTML</title></head>

297

<body><h1>Hello, HTML!</h1></body>

298

</html>

299

"""

300

return html_content

301

302

@app.get("/text", response_class=PlainTextResponse)

303

def get_text():

304

return "Hello, plain text!"

305

306

@app.get("/redirect")

307

def redirect_to_docs():

308

return RedirectResponse(url="/docs")

309

310

@app.get("/permanent-redirect")

311

def permanent_redirect():

312

return RedirectResponse(url="/new-location", status_code=301)

313

```

314

315

### File Downloads

316

317

```python

318

from fastapi import FastAPI

319

from fastapi.responses import FileResponse

320

import tempfile

321

import os

322

323

app = FastAPI()

324

325

@app.get("/download-file")

326

def download_file():

327

# Create a temporary file

328

with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as f:

329

f.write("This is a downloadable file content.")

330

temp_file_path = f.name

331

332

return FileResponse(

333

path=temp_file_path,

334

filename="download.txt",

335

media_type="text/plain"

336

)

337

338

@app.get("/download-image")

339

def download_image():

340

# Serve an existing file

341

file_path = "/path/to/image.jpg"

342

return FileResponse(

343

path=file_path,

344

filename="image.jpg",

345

media_type="image/jpeg"

346

)

347

```

348

349

### Streaming Responses

350

351

```python

352

from fastapi import FastAPI

353

from fastapi.responses import StreamingResponse

354

import io

355

import json

356

357

app = FastAPI()

358

359

@app.get("/stream-data")

360

def stream_data():

361

def generate_data():

362

for i in range(1000):

363

data = {"item": i, "value": f"data_{i}"}

364

yield f"data: {json.dumps(data)}\n"

365

366

return StreamingResponse(

367

generate_data(),

368

media_type="text/plain"

369

)

370

371

@app.get("/stream-csv")

372

def stream_csv():

373

def generate_csv():

374

yield "id,name,email\n"

375

for i in range(1000):

376

yield f"{i},user_{i},user_{i}@example.com\n"

377

378

return StreamingResponse(

379

generate_csv(),

380

media_type="text/csv",

381

headers={"Content-Disposition": "attachment; filename=users.csv"}

382

)

383

384

@app.get("/stream-file")

385

def stream_large_file():

386

def iterfile(file_path: str):

387

with open(file_path, mode="rb") as file_like:

388

while True:

389

chunk = file_like.read(1024)

390

if not chunk:

391

break

392

yield chunk

393

394

return StreamingResponse(

395

iterfile("/path/to/large/file.bin"),

396

media_type="application/octet-stream"

397

)

398

```

399

400

### File Upload Handling

401

402

```python

403

from fastapi import FastAPI, File, UploadFile, HTTPException

404

from typing import List

405

import aiofiles

406

import os

407

408

app = FastAPI()

409

410

@app.post("/upload-file/")

411

async def upload_file(file: UploadFile = File(...)):

412

# Validate file type

413

if not file.content_type.startswith("image/"):

414

raise HTTPException(400, "File must be an image")

415

416

# Read file content

417

content = await file.read()

418

419

# Save file

420

file_path = f"uploads/{file.filename}"

421

async with aiofiles.open(file_path, "wb") as f:

422

await f.write(content)

423

424

return {

425

"filename": file.filename,

426

"content_type": file.content_type,

427

"size": len(content),

428

"saved_to": file_path

429

}

430

431

@app.post("/upload-multiple/")

432

async def upload_multiple_files(files: List[UploadFile] = File(...)):

433

uploaded_files = []

434

435

for file in files:

436

content = await file.read()

437

file_info = {

438

"filename": file.filename,

439

"content_type": file.content_type,

440

"size": len(content)

441

}

442

uploaded_files.append(file_info)

443

444

# Reset file pointer if you need to read again

445

await file.seek(0)

446

447

return {"uploaded_files": uploaded_files}

448

449

@app.post("/process-file/")

450

async def process_file(file: UploadFile = File(...)):

451

# Process file line by line for large files

452

processed_lines = []

453

454

# Read file line by line

455

content = await file.read()

456

lines = content.decode().split('\n')

457

458

for i, line in enumerate(lines):

459

if line.strip(): # Skip empty lines

460

processed_lines.append(f"Line {i+1}: {line.strip()}")

461

462

await file.close()

463

464

return {

465

"filename": file.filename,

466

"total_lines": len(processed_lines),

467

"processed_lines": processed_lines[:10] # Return first 10 lines

468

}

469

```

470

471

### Custom Response with Headers

472

473

```python

474

from fastapi import FastAPI, Response

475

from fastapi.responses import JSONResponse

476

477

app = FastAPI()

478

479

@app.get("/custom-headers")

480

def custom_headers():

481

content = {"message": "Custom headers response"}

482

headers = {

483

"X-Custom-Header": "Custom Value",

484

"X-Processing-Time": "0.123",

485

"Cache-Control": "no-cache"

486

}

487

return JSONResponse(content=content, headers=headers)

488

489

@app.get("/set-cookie")

490

def set_cookie(response: Response):

491

content = {"message": "Cookie set"}

492

response.set_cookie(

493

key="session_id",

494

value="abc123",

495

max_age=3600,

496

httponly=True,

497

secure=True,

498

samesite="lax"

499

)

500

return content

501

502

@app.get("/custom-status")

503

def custom_status():

504

return JSONResponse(

505

content={"message": "Created successfully"},

506

status_code=201,

507

headers={"Location": "/items/123"}

508

)

509

```

510

511

### Response Model with Custom Response Class

512

513

```python

514

from fastapi import FastAPI

515

from fastapi.responses import ORJSONResponse

516

from pydantic import BaseModel

517

from typing import List

518

519

app = FastAPI(default_response_class=ORJSONResponse)

520

521

class Item(BaseModel):

522

id: int

523

name: str

524

price: float

525

526

@app.get("/items", response_model=List[Item])

527

def get_items():

528

# FastAPI will use ORJSONResponse for serialization

529

return [

530

{"id": 1, "name": "Item 1", "price": 10.5},

531

{"id": 2, "name": "Item 2", "price": 20.0}

532

]

533

534

@app.get("/custom-json", response_class=ORJSONResponse)

535

def get_custom_json():

536

# Explicitly use ORJSONResponse

537

return {"message": "Fast JSON response"}

538

```