or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-routing.mdconfiguration.mddto.mdexceptions.mdhttp-handlers.mdindex.mdmiddleware.mdopenapi.mdplugins.mdrequest-response.mdsecurity.mdtesting.mdwebsocket.md

request-response.mddocs/

0

# Request and Response

1

2

Connection objects for accessing request data and generating responses. The Request object provides access to HTTP request data including headers, body, query parameters, and path parameters. Response objects handle returning different content types and status codes.

3

4

## Capabilities

5

6

### Request Object

7

8

The Request object provides access to all aspects of an incoming HTTP request through a rich API for headers, body parsing, parameters, and more.

9

10

```python { .api }

11

class Request(ASGIConnection):

12

def __init__(self, scope: Scope, receive: Receive = empty_receive):

13

"""

14

Initialize a Request object.

15

16

Parameters:

17

- scope: ASGI scope dictionary

18

- receive: ASGI receive callable

19

"""

20

21

# Body parsing methods

22

async def body(self) -> bytes:

23

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

24

25

async def json(self) -> Any:

26

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

27

28

async def form(self) -> dict[str, str | list[str]]:

29

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

30

31

async def msgpack(self) -> Any:

32

"""Parse request body as MessagePack."""

33

34

async def stream(self) -> AsyncIterator[bytes]:

35

"""Stream the request body in chunks."""

36

37

# Parameter access

38

@property

39

def query_params(self) -> MultiDict[str, str]:

40

"""Get query parameters as a MultiDict."""

41

42

@property

43

def path_params(self) -> dict[str, Any]:

44

"""Get path parameters with type conversion."""

45

46

# Headers and cookies

47

@property

48

def headers(self) -> Headers:

49

"""Get request headers."""

50

51

@property

52

def cookies(self) -> dict[str, str]:

53

"""Get request cookies."""

54

55

# Request metadata

56

@property

57

def method(self) -> Method:

58

"""Get HTTP method."""

59

60

@property

61

def url(self) -> URL:

62

"""Get request URL."""

63

64

@property

65

def content_type(self) -> tuple[str, dict[str, str]]:

66

"""Get content type and parameters."""

67

68

@property

69

def client(self) -> Address | None:

70

"""Get client address."""

71

72

@property

73

def auth(self) -> Any:

74

"""Get authentication information."""

75

76

@property

77

def user(self) -> Any:

78

"""Get authenticated user."""

79

80

@property

81

def state(self) -> State:

82

"""Get request state."""

83

84

@property

85

def session(self) -> dict[str, Any]:

86

"""Get session data."""

87

88

# Request matching

89

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

90

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

91

92

def url_for_static_asset(self, name: str, file_path: str) -> str:

93

"""Generate URL for static asset."""

94

```

95

96

### Response Objects

97

98

Response objects handle different content types and response configurations.

99

100

```python { .api }

101

class Response:

102

def __init__(

103

self,

104

content: Any = None,

105

*,

106

status_code: int = 200,

107

headers: ResponseHeaders | None = None,

108

media_type: MediaType | str | None = None,

109

background: BackgroundTask | BackgroundTasks | None = None,

110

cookies: Sequence[Cookie] | None = None,

111

encoding: str = "utf-8",

112

):

113

"""

114

Create a Response object.

115

116

Parameters:

117

- content: Response content (automatically serialized)

118

- status_code: HTTP status code

119

- headers: Response headers

120

- media_type: Content media type

121

- background: Background task(s) to execute after response

122

- cookies: Response cookies

123

- encoding: Content encoding

124

"""

125

126

@property

127

def content(self) -> bytes:

128

"""Get response content as bytes."""

129

130

def set_header(self, key: str, value: str) -> None:

131

"""Set a response header."""

132

133

def set_cookie(

134

self,

135

key: str,

136

value: str | None = None,

137

*,

138

max_age: int | None = None,

139

expires: int | datetime | None = None,

140

path: str = "/",

141

domain: str | None = None,

142

secure: bool = False,

143

httponly: bool = False,

144

samesite: Literal["lax", "strict", "none"] = "lax",

145

) -> None:

146

"""Set a response cookie."""

147

148

def delete_cookie(

149

self,

150

key: str,

151

path: str = "/",

152

domain: str | None = None,

153

) -> None:

154

"""Delete a cookie."""

155

```

156

157

### File Response

158

159

Response for serving files with proper headers and streaming support.

160

161

```python { .api }

162

class File(Response):

163

def __init__(

164

self,

165

path: str | Path,

166

*,

167

filename: str | None = None,

168

stat_result: os.stat_result | None = None,

169

chunk_size: int = 1024 * 1024,

170

content_disposition_type: Literal["attachment", "inline"] = "attachment",

171

etag: ETag | None = None,

172

**kwargs: Any,

173

):

174

"""

175

Create a file response.

176

177

Parameters:

178

- path: Path to the file

179

- filename: Override filename in Content-Disposition header

180

- stat_result: Pre-computed file stat result

181

- chunk_size: Size of chunks for streaming

182

- content_disposition_type: Content disposition type

183

- etag: ETag configuration

184

"""

185

```

186

187

### Streaming Response

188

189

Response for streaming data to the client.

190

191

```python { .api }

192

class Stream(Response):

193

def __init__(

194

self,

195

iterator: Iterator[str | bytes] | AsyncIterator[str | bytes],

196

*,

197

media_type: MediaType | str = MediaType.TEXT,

198

**kwargs: Any,

199

):

200

"""

201

Create a streaming response.

202

203

Parameters:

204

- iterator: Iterator yielding response chunks

205

- media_type: Content media type

206

"""

207

```

208

209

### Redirect Response

210

211

Response for HTTP redirects.

212

213

```python { .api }

214

class Redirect(Response):

215

def __init__(

216

self,

217

path: str,

218

*,

219

status_code: int = HTTP_302_FOUND,

220

**kwargs: Any,

221

):

222

"""

223

Create a redirect response.

224

225

Parameters:

226

- path: Redirect target URL

227

- status_code: HTTP redirect status code

228

"""

229

```

230

231

### Template Response

232

233

Response for rendered templates.

234

235

```python { .api }

236

class Template(Response):

237

def __init__(

238

self,

239

name: str,

240

context: dict[str, Any] | None = None,

241

*,

242

**kwargs: Any,

243

):

244

"""

245

Create a template response.

246

247

Parameters:

248

- name: Template name

249

- context: Template context variables

250

"""

251

```

252

253

### Server-Sent Events

254

255

Response for server-sent events streaming.

256

257

```python { .api }

258

class ServerSentEvent(Response):

259

def __init__(

260

self,

261

iterator: Iterator[ServerSentEventMessage] | AsyncIterator[ServerSentEventMessage],

262

*,

263

**kwargs: Any,

264

):

265

"""

266

Create a server-sent events response.

267

268

Parameters:

269

- iterator: Iterator yielding SSE messages

270

"""

271

272

class ServerSentEventMessage:

273

def __init__(

274

self,

275

data: str | bytes | dict | list,

276

*,

277

event: str | None = None,

278

id: str | None = None,

279

retry: int | None = None,

280

comment: str | None = None,

281

):

282

"""

283

Create an SSE message.

284

285

Parameters:

286

- data: Message data

287

- event: Event type

288

- id: Message ID

289

- retry: Retry interval in milliseconds

290

- comment: Comment text

291

"""

292

```

293

294

### Data Structures

295

296

Core data structures used in requests and responses.

297

298

```python { .api }

299

class Headers(CaseInsensitiveDict[str]):

300

"""Case-insensitive HTTP headers dictionary."""

301

302

def __init__(self, headers: Mapping[str, str] | RawHeaders | None = None):

303

"""Initialize headers from mapping or raw headers."""

304

305

def add(self, key: str, value: str) -> None:

306

"""Add a header value (allows duplicates)."""

307

308

def get_list(self, key: str) -> list[str]:

309

"""Get all values for a header as a list."""

310

311

class MultiDict(dict[str, str]):

312

"""Dictionary supporting multiple values per key."""

313

314

def getlist(self, key: str) -> list[str]:

315

"""Get all values for a key as a list."""

316

317

def add(self, key: str, value: str) -> None:

318

"""Add a value for a key."""

319

320

class Cookie:

321

def __init__(

322

self,

323

key: str,

324

value: str | None = None,

325

*,

326

max_age: int | None = None,

327

expires: int | datetime | None = None,

328

path: str = "/",

329

domain: str | None = None,

330

secure: bool = False,

331

httponly: bool = False,

332

samesite: Literal["lax", "strict", "none"] = "lax",

333

):

334

"""Create a cookie."""

335

336

class URL:

337

def __init__(self, url: str = ""):

338

"""Parse a URL string."""

339

340

@property

341

def scheme(self) -> str:

342

"""Get URL scheme."""

343

344

@property

345

def hostname(self) -> str | None:

346

"""Get hostname."""

347

348

@property

349

def port(self) -> int | None:

350

"""Get port number."""

351

352

@property

353

def path(self) -> str:

354

"""Get URL path."""

355

356

@property

357

def query(self) -> str:

358

"""Get query string."""

359

360

@property

361

def fragment(self) -> str:

362

"""Get URL fragment."""

363

364

def replace(self, **kwargs: Any) -> URL:

365

"""Create a new URL with replaced components."""

366

```

367

368

## Usage Examples

369

370

### Request Data Access

371

372

```python

373

from litestar import get, post, Request

374

from litestar.exceptions import ValidationException

375

376

@get("/info")

377

async def request_info(request: Request) -> dict:

378

return {

379

"method": request.method,

380

"url": str(request.url),

381

"headers": dict(request.headers),

382

"query_params": dict(request.query_params),

383

"client": request.client.host if request.client else None,

384

}

385

386

@get("/search")

387

async def search(request: Request) -> dict:

388

query = request.query_params.get("q", "")

389

limit = int(request.query_params.get("limit", "10"))

390

391

return {

392

"query": query,

393

"limit": limit,

394

"results": [] # Search results would go here

395

}

396

397

@post("/data")

398

async def handle_data(request: Request) -> dict:

399

content_type = request.headers.get("content-type", "")

400

401

if "application/json" in content_type:

402

data = await request.json()

403

elif "application/x-www-form-urlencoded" in content_type:

404

data = await request.form()

405

else:

406

raise ValidationException("Unsupported content type")

407

408

return {"received": data}

409

```

410

411

### Custom Response Types

412

413

```python

414

from litestar import get

415

from litestar.response import Response, File, Stream, Redirect

416

from litestar.status_codes import HTTP_201_CREATED

417

import json

418

419

@get("/custom")

420

async def custom_response() -> Response:

421

data = {"message": "Custom response"}

422

return Response(

423

content=json.dumps(data),

424

status_code=HTTP_201_CREATED,

425

headers={"X-Custom-Header": "value"},

426

media_type="application/json"

427

)

428

429

@get("/download/{filename:str}")

430

async def download_file(filename: str) -> File:

431

return File(

432

path=f"/uploads/{filename}",

433

filename=filename,

434

content_disposition_type="attachment"

435

)

436

437

@get("/stream-data")

438

async def stream_data() -> Stream:

439

async def generate_data():

440

for i in range(100):

441

yield f"chunk {i}\n"

442

443

return Stream(

444

iterator=generate_data(),

445

media_type="text/plain"

446

)

447

448

@get("/redirect-to-docs")

449

async def redirect_to_docs() -> Redirect:

450

return Redirect("https://docs.litestar.dev")

451

```

452

453

### Cookie Handling

454

455

```python

456

from litestar import get, post, Request, Response

457

458

@post("/login")

459

async def login(request: Request) -> Response:

460

# Authenticate user (simplified)

461

user_data = await request.json()

462

463

response = Response({"status": "logged in"})

464

response.set_cookie(

465

"session_id",

466

"abc123",

467

max_age=3600, # 1 hour

468

httponly=True,

469

secure=True,

470

samesite="strict"

471

)

472

return response

473

474

@get("/profile")

475

async def get_profile(request: Request) -> dict:

476

session_id = request.cookies.get("session_id")

477

if not session_id:

478

return {"error": "Not authenticated"}

479

480

return {"user": "alice", "session": session_id}

481

482

@post("/logout")

483

async def logout() -> Response:

484

response = Response({"status": "logged out"})

485

response.delete_cookie("session_id")

486

return response

487

```

488

489

### Server-Sent Events

490

491

```python

492

from litestar import get

493

from litestar.response import ServerSentEvent, ServerSentEventMessage

494

import asyncio

495

496

@get("/events")

497

async def event_stream() -> ServerSentEvent:

498

async def generate_events():

499

counter = 0

500

while True:

501

yield ServerSentEventMessage(

502

data={"timestamp": time.time(), "counter": counter},

503

event="update",

504

id=str(counter)

505

)

506

counter += 1

507

await asyncio.sleep(1)

508

509

return ServerSentEvent(generate_events())

510

```

511

512

### File Upload Handling

513

514

```python

515

from litestar import post, Request

516

from litestar.datastructures import UploadFile

517

518

@post("/upload")

519

async def upload_file(request: Request) -> dict:

520

form_data = await request.form()

521

522

uploaded_file = form_data.get("file")

523

if isinstance(uploaded_file, UploadFile):

524

content = await uploaded_file.read()

525

return {

526

"filename": uploaded_file.filename,

527

"size": len(content),

528

"content_type": uploaded_file.content_type

529

}

530

531

return {"error": "No file uploaded"}

532

```

533

534

## Types

535

536

```python { .api }

537

# ASGI types

538

Scope = dict[str, Any]

539

Receive = Callable[[], Awaitable[Message]]

540

Send = Callable[[Message], Awaitable[None]]

541

Message = dict[str, Any]

542

543

# HTTP types

544

Method = Literal["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE"]

545

ResponseHeaders = Mapping[str, str] | Sequence[tuple[str, str]]

546

RawHeaders = list[tuple[bytes, bytes]]

547

548

# Content types

549

ContentType = tuple[str, dict[str, str]]

550

551

# Iterator types for streaming

552

SyncIterator = Iterator[str | bytes]

553

AsyncIterator = AsyncIterator[str | bytes]

554

```