or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdasgi-websocket.mderror-handling.mdindex.mdmedia.mdmiddleware-hooks.mdrequest-response.mdrouting.mdtesting.mdutilities.md

media.mddocs/

0

# Media Processing

1

2

Pluggable media handling system for serializing and deserializing request/response bodies. Supports JSON, MessagePack, multipart forms, URL-encoded data, and custom media types with extensible handler architecture.

3

4

## Capabilities

5

6

### Base Media Handler Classes

7

8

Foundation classes for implementing custom media processors.

9

10

```python { .api }

11

class BaseHandler:

12

def serialize(self, media: object, content_type: str) -> bytes:

13

"""

14

Serialize Python object to bytes.

15

16

Args:

17

media: Python object to serialize

18

content_type: MIME content type

19

20

Returns:

21

Serialized bytes

22

"""

23

24

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

25

"""

26

Deserialize bytes stream to Python object.

27

28

Args:

29

stream: Input byte stream

30

content_type: MIME content type

31

content_length: Content length in bytes

32

33

Returns:

34

Deserialized Python object

35

"""

36

37

class TextBaseHandlerWS:

38

def serialize(self, media: object) -> str:

39

"""

40

Serialize Python object to text for WebSocket.

41

42

Args:

43

media: Python object to serialize

44

45

Returns:

46

Serialized text string

47

"""

48

49

def deserialize(self, payload: str) -> object:

50

"""

51

Deserialize text payload to Python object.

52

53

Args:

54

payload: Text payload from WebSocket

55

56

Returns:

57

Deserialized Python object

58

"""

59

60

class BinaryBaseHandlerWS:

61

def serialize(self, media: object) -> bytes:

62

"""

63

Serialize Python object to bytes for WebSocket.

64

65

Args:

66

media: Python object to serialize

67

68

Returns:

69

Serialized bytes

70

"""

71

72

def deserialize(self, payload: bytes) -> object:

73

"""

74

Deserialize binary payload to Python object.

75

76

Args:

77

payload: Binary payload from WebSocket

78

79

Returns:

80

Deserialized Python object

81

"""

82

```

83

84

### Media Handler Registry

85

86

Central registry for managing media type handlers and content negotiation.

87

88

```python { .api }

89

class Handlers:

90

def __init__(self, initial: dict = None):

91

"""

92

Create media handler registry.

93

94

Args:

95

initial: Initial handler mappings {media_type: handler}

96

"""

97

98

def find_by_media_type(self, media_type: str, default: object = None) -> BaseHandler:

99

"""

100

Find handler for specific media type.

101

102

Args:

103

media_type: MIME media type (e.g., 'application/json')

104

default: Default handler if none found

105

106

Returns:

107

Media handler instance or default

108

"""

109

110

def __setitem__(self, media_type: str, handler: BaseHandler):

111

"""

112

Register handler for media type.

113

114

Args:

115

media_type: MIME media type

116

handler: Handler instance

117

"""

118

119

def __getitem__(self, media_type: str) -> BaseHandler:

120

"""

121

Get handler for media type.

122

123

Args:

124

media_type: MIME media type

125

126

Returns:

127

Handler instance

128

"""

129

130

class MissingDependencyHandler:

131

def __init__(self, library: str, media_type: str):

132

"""

133

Placeholder handler when dependencies are missing.

134

135

Args:

136

library: Name of missing library

137

media_type: Media type this handler would support

138

"""

139

140

def serialize(self, media: object, content_type: str = None) -> bytes:

141

"""Raises error about missing dependency"""

142

143

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

144

"""Raises error about missing dependency"""

145

```

146

147

#### Handler Registry Usage

148

149

```python

150

import falcon

151

152

# Create custom handlers registry

153

handlers = falcon.media.Handlers({

154

'application/json': falcon.media.JSONHandler(),

155

'application/msgpack': falcon.media.MessagePackHandler(),

156

})

157

158

# Configure app with custom handlers

159

req_options = falcon.RequestOptions(media_handlers=handlers)

160

resp_options = falcon.ResponseOptions(media_handlers=handlers)

161

162

app = falcon.App(

163

req_options=req_options,

164

resp_options=resp_options

165

)

166

```

167

168

### Built-in JSON Handler

169

170

High-performance JSON serialization and deserialization using standard library or orjson.

171

172

```python { .api }

173

class JSONHandler(BaseHandler):

174

def __init__(self, loads: callable = None, dumps: callable = None):

175

"""

176

JSON media handler.

177

178

Args:

179

loads: Custom JSON decoder function

180

dumps: Custom JSON encoder function

181

"""

182

183

def serialize(self, media: object, content_type: str = None) -> bytes:

184

"""

185

Serialize Python object to JSON bytes.

186

187

Args:

188

media: Python object (dict, list, etc.)

189

content_type: Content type (ignored)

190

191

Returns:

192

JSON bytes

193

"""

194

195

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

196

"""

197

Deserialize JSON bytes to Python object.

198

199

Args:

200

stream: JSON byte stream

201

content_type: Content type (ignored)

202

content_length: Content length

203

204

Returns:

205

Python object

206

"""

207

208

class JSONHandlerWS(TextBaseHandlerWS):

209

def __init__(self, loads: callable = None, dumps: callable = None):

210

"""

211

JSON WebSocket handler.

212

213

Args:

214

loads: Custom JSON decoder function

215

dumps: Custom JSON encoder function

216

"""

217

```

218

219

### MessagePack Handler

220

221

Efficient MessagePack binary serialization support.

222

223

```python { .api }

224

class MessagePackHandler(BaseHandler):

225

def __init__(self, **kwargs):

226

"""

227

MessagePack media handler.

228

229

Args:

230

**kwargs: Additional options for msgpack

231

"""

232

233

def serialize(self, media: object, content_type: str = None) -> bytes:

234

"""

235

Serialize Python object to MessagePack bytes.

236

237

Args:

238

media: Python object

239

content_type: Content type (ignored)

240

241

Returns:

242

MessagePack bytes

243

"""

244

245

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

246

"""

247

Deserialize MessagePack bytes to Python object.

248

249

Args:

250

stream: MessagePack byte stream

251

content_type: Content type (ignored)

252

content_length: Content length

253

254

Returns:

255

Python object

256

"""

257

258

class MessagePackHandlerWS(BinaryBaseHandlerWS):

259

def __init__(self, **kwargs):

260

"""

261

MessagePack WebSocket handler.

262

263

Args:

264

**kwargs: Additional options for msgpack

265

"""

266

```

267

268

### Multipart Form Handler

269

270

Support for multipart/form-data file uploads and form processing.

271

272

```python { .api }

273

class MultipartFormHandler(BaseHandler):

274

def __init__(self):

275

"""Multipart form data handler."""

276

277

def serialize(self, media: object, content_type: str = None) -> bytes:

278

"""

279

Serialize form data to multipart bytes.

280

281

Args:

282

media: Form data dictionary

283

content_type: Content type with boundary

284

285

Returns:

286

Multipart bytes

287

"""

288

289

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

290

"""

291

Parse multipart form data from stream.

292

293

Args:

294

stream: Multipart byte stream

295

content_type: Content type with boundary parameter

296

content_length: Content length

297

298

Returns:

299

Form data dictionary

300

"""

301

```

302

303

#### Multipart Usage Example

304

305

```python

306

class FileUploadResource:

307

def on_post(self, req, resp):

308

"""Handle file upload"""

309

# req.media contains parsed multipart data

310

form_data = req.media

311

312

# Access uploaded file

313

uploaded_file = form_data.get('file')

314

if uploaded_file:

315

# Process file upload

316

filename = uploaded_file.filename

317

content_type = uploaded_file.content_type

318

file_data = uploaded_file.data # or use .stream

319

320

# Save file

321

save_uploaded_file(filename, file_data)

322

323

resp.status = falcon.HTTP_201

324

resp.media = {'uploaded': filename}

325

else:

326

raise falcon.HTTPBadRequest(

327

title='Missing file',

328

description='No file provided in upload'

329

)

330

```

331

332

### URL-Encoded Form Handler

333

334

Support for application/x-www-form-urlencoded form data.

335

336

```python { .api }

337

class URLEncodedFormHandler(BaseHandler):

338

def __init__(self):

339

"""URL-encoded form handler."""

340

341

def serialize(self, media: object, content_type: str = None) -> bytes:

342

"""

343

Serialize form data to URL-encoded bytes.

344

345

Args:

346

media: Form data dictionary

347

content_type: Content type (ignored)

348

349

Returns:

350

URL-encoded bytes

351

"""

352

353

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

354

"""

355

Parse URL-encoded form data from stream.

356

357

Args:

358

stream: URL-encoded byte stream

359

content_type: Content type (ignored)

360

content_length: Content length

361

362

Returns:

363

Form data dictionary

364

"""

365

```

366

367

### Media Validation

368

369

JSON Schema validation support for request/response media.

370

371

```python { .api }

372

# Validation support (falcon.media.validators.jsonschema module)

373

def validate(schema: dict) -> callable:

374

"""

375

Create JSON Schema validator decorator.

376

377

Args:

378

schema: JSON Schema dictionary

379

380

Returns:

381

Decorator function for validation

382

"""

383

```

384

385

#### Validation Example

386

387

```python

388

from falcon.media.validators import jsonschema

389

390

user_schema = {

391

'type': 'object',

392

'properties': {

393

'name': {'type': 'string', 'minLength': 1},

394

'email': {'type': 'string', 'format': 'email'},

395

'age': {'type': 'integer', 'minimum': 0}

396

},

397

'required': ['name', 'email']

398

}

399

400

class UserResource:

401

@jsonschema.validate(req_schema=user_schema)

402

def on_post(self, req, resp):

403

# req.media is automatically validated against schema

404

user_data = req.media

405

new_user = create_user(user_data)

406

resp.status = falcon.HTTP_201

407

resp.media = new_user

408

```

409

410

### Custom Media Handler

411

412

Creating custom media handlers for specialized content types.

413

414

```python { .api }

415

class CustomHandler(BaseHandler):

416

def __init__(self, **options):

417

"""

418

Custom media handler implementation.

419

420

Args:

421

**options: Handler-specific options

422

"""

423

424

def serialize(self, media: object, content_type: str = None) -> bytes:

425

"""Implement custom serialization logic"""

426

427

def deserialize(self, stream: object, content_type: str, content_length: int) -> object:

428

"""Implement custom deserialization logic"""

429

```

430

431

#### Custom Handler Example

432

433

```python

434

import yaml

435

import falcon

436

437

class YAMLHandler(falcon.media.BaseHandler):

438

"""Custom YAML media handler"""

439

440

def serialize(self, media, content_type=None):

441

"""Serialize Python object to YAML"""

442

return yaml.dump(media, default_flow_style=False).encode('utf-8')

443

444

def deserialize(self, stream, content_type, content_length):

445

"""Deserialize YAML to Python object"""

446

data = stream.read(content_length).decode('utf-8')

447

return yaml.safe_load(data)

448

449

# Register custom handler

450

app = falcon.App()

451

app.req_options.media_handlers['application/yaml'] = YAMLHandler()

452

app.resp_options.media_handlers['application/yaml'] = YAMLHandler()

453

454

class YAMLResource:

455

def on_post(self, req, resp):

456

# Automatically uses YAML handler based on Content-Type

457

data = req.media # YAML parsed to Python object

458

resp.content_type = 'application/yaml'

459

resp.media = {'processed': data} # Python object serialized to YAML

460

```

461

462

### Error Handling

463

464

Media processing specific error classes for robust error handling.

465

466

```python { .api }

467

class MediaNotFoundError(Exception):

468

"""Raised when no media handler found for content type"""

469

470

class MediaMalformedError(Exception):

471

"""Raised when media content is malformed or invalid"""

472

473

class MediaValidationError(Exception):

474

"""Raised when media validation fails"""

475

476

class MultipartParseError(Exception):

477

"""Raised when multipart form parsing fails"""

478

```

479

480

## Types

481

482

```python { .api }

483

# Media handler base classes

484

BaseHandler: type

485

TextBaseHandlerWS: type

486

BinaryBaseHandlerWS: type

487

488

# Handler registry

489

Handlers: type

490

MissingDependencyHandler: type

491

492

# Built-in handlers

493

JSONHandler: type

494

JSONHandlerWS: type

495

MessagePackHandler: type

496

MessagePackHandlerWS: type

497

MultipartFormHandler: type

498

URLEncodedFormHandler: type

499

500

# Validation

501

falcon.media.validators.jsonschema.validate: callable

502

503

# Media errors

504

MediaNotFoundError: type

505

MediaMalformedError: type

506

MediaValidationError: type

507

MultipartParseError: type

508

```