or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client.mddata.mdindex.mdserver.mdtesting.mdutilities.mdwebsocket.md

utilities.mddocs/

0

# Utilities

1

2

Supporting utilities and extensions including request tracing, DNS resolution, authentication helpers, compression configuration, and Gunicorn worker integration. These utilities provide integration points, performance optimization, and extensibility features for aiohttp applications.

3

4

## Capabilities

5

6

### Request Tracing

7

8

Comprehensive request tracing system for monitoring and debugging HTTP client operations with detailed event tracking.

9

10

```python { .api }

11

class TraceConfig:

12

def __init__(self):

13

"""Create trace configuration."""

14

15

def on_request_start(self, callback):

16

"""

17

Register request start callback.

18

19

Parameters:

20

- callback: Async function receiving TraceRequestStartParams

21

"""

22

23

def on_request_end(self, callback):

24

"""

25

Register request end callback.

26

27

Parameters:

28

- callback: Async function receiving TraceRequestEndParams

29

"""

30

31

def on_request_exception(self, callback):

32

"""

33

Register request exception callback.

34

35

Parameters:

36

- callback: Async function receiving TraceRequestExceptionParams

37

"""

38

39

def on_request_redirect(self, callback):

40

"""

41

Register request redirect callback.

42

43

Parameters:

44

- callback: Async function receiving TraceRequestRedirectParams

45

"""

46

47

def on_request_headers_sent(self, callback):

48

"""

49

Register request headers sent callback.

50

51

Parameters:

52

- callback: Async function receiving TraceRequestHeadersSentParams

53

"""

54

55

def on_request_chunk_sent(self, callback):

56

"""

57

Register request chunk sent callback.

58

59

Parameters:

60

- callback: Async function receiving TraceRequestChunkSentParams

61

"""

62

63

def on_response_chunk_received(self, callback):

64

"""

65

Register response chunk received callback.

66

67

Parameters:

68

- callback: Async function receiving TraceResponseChunkReceivedParams

69

"""

70

71

def on_connection_create_start(self, callback):

72

"""

73

Register connection creation start callback.

74

75

Parameters:

76

- callback: Async function receiving TraceConnectionCreateStartParams

77

"""

78

79

def on_connection_create_end(self, callback):

80

"""

81

Register connection creation end callback.

82

83

Parameters:

84

- callback: Async function receiving TraceConnectionCreateEndParams

85

"""

86

87

def on_connection_queued_start(self, callback):

88

"""

89

Register connection queued start callback.

90

91

Parameters:

92

- callback: Async function receiving TraceConnectionQueuedStartParams

93

"""

94

95

def on_connection_queued_end(self, callback):

96

"""

97

Register connection queued end callback.

98

99

Parameters:

100

- callback: Async function receiving TraceConnectionQueuedEndParams

101

"""

102

103

def on_connection_reuseconn(self, callback):

104

"""

105

Register connection reuse callback.

106

107

Parameters:

108

- callback: Async function receiving TraceConnectionReuseconnParams

109

"""

110

111

def on_dns_resolvehost_start(self, callback):

112

"""

113

Register DNS resolve start callback.

114

115

Parameters:

116

- callback: Async function receiving TraceDnsResolveHostStartParams

117

"""

118

119

def on_dns_resolvehost_end(self, callback):

120

"""

121

Register DNS resolve end callback.

122

123

Parameters:

124

- callback: Async function receiving TraceDnsResolveHostEndParams

125

"""

126

127

def on_dns_cache_hit(self, callback):

128

"""

129

Register DNS cache hit callback.

130

131

Parameters:

132

- callback: Async function receiving TraceDnsCacheHitParams

133

"""

134

135

def on_dns_cache_miss(self, callback):

136

"""

137

Register DNS cache miss callback.

138

139

Parameters:

140

- callback: Async function receiving TraceDnsCacheMissParams

141

"""

142

143

# Trace event parameter classes

144

class TraceRequestStartParams:

145

"""Request start trace parameters."""

146

@property

147

def method(self): ...

148

@property

149

def url(self): ...

150

@property

151

def headers(self): ...

152

153

class TraceRequestEndParams:

154

"""Request end trace parameters."""

155

@property

156

def method(self): ...

157

@property

158

def url(self): ...

159

@property

160

def headers(self): ...

161

@property

162

def response(self): ...

163

164

class TraceRequestExceptionParams:

165

"""Request exception trace parameters."""

166

@property

167

def method(self): ...

168

@property

169

def url(self): ...

170

@property

171

def headers(self): ...

172

@property

173

def exception(self): ...

174

175

class TraceRequestRedirectParams:

176

"""Request redirect trace parameters."""

177

@property

178

def method(self): ...

179

@property

180

def url(self): ...

181

@property

182

def headers(self): ...

183

@property

184

def response(self): ...

185

186

class TraceRequestHeadersSentParams:

187

"""Request headers sent trace parameters."""

188

@property

189

def method(self): ...

190

@property

191

def url(self): ...

192

@property

193

def headers(self): ...

194

195

class TraceRequestChunkSentParams:

196

"""Request chunk sent trace parameters."""

197

@property

198

def method(self): ...

199

@property

200

def url(self): ...

201

@property

202

def chunk(self): ...

203

204

class TraceResponseChunkReceivedParams:

205

"""Response chunk received trace parameters."""

206

@property

207

def method(self): ...

208

@property

209

def url(self): ...

210

@property

211

def chunk(self): ...

212

213

class TraceConnectionCreateStartParams:

214

"""Connection creation start trace parameters."""

215

pass

216

217

class TraceConnectionCreateEndParams:

218

"""Connection creation end trace parameters."""

219

pass

220

221

class TraceConnectionQueuedStartParams:

222

"""Connection queued start trace parameters."""

223

pass

224

225

class TraceConnectionQueuedEndParams:

226

"""Connection queued end trace parameters."""

227

pass

228

229

class TraceConnectionReuseconnParams:

230

"""Connection reuse trace parameters."""

231

pass

232

233

class TraceDnsResolveHostStartParams:

234

"""DNS resolve start trace parameters."""

235

@property

236

def host(self): ...

237

238

class TraceDnsResolveHostEndParams:

239

"""DNS resolve end trace parameters."""

240

@property

241

def host(self): ...

242

243

class TraceDnsCacheHitParams:

244

"""DNS cache hit trace parameters."""

245

@property

246

def host(self): ...

247

248

class TraceDnsCacheMissParams:

249

"""DNS cache miss trace parameters."""

250

@property

251

def host(self): ...

252

```

253

254

### DNS Resolution

255

256

Configurable DNS resolution with support for different resolver implementations and caching strategies.

257

258

```python { .api }

259

class AsyncResolver:

260

def __init__(self, loop=None):

261

"""

262

Asynchronous DNS resolver.

263

264

Parameters:

265

- loop: Event loop

266

"""

267

268

async def resolve(self, hostname, port=0, family=0):

269

"""

270

Resolve hostname to addresses.

271

272

Parameters:

273

- hostname (str): Hostname to resolve

274

- port (int): Port number

275

- family (int): Address family

276

277

Returns:

278

List of resolved addresses

279

"""

280

281

async def close(self):

282

"""Close resolver resources."""

283

284

class DefaultResolver:

285

def __init__(self, loop=None):

286

"""

287

Default system DNS resolver.

288

289

Parameters:

290

- loop: Event loop

291

"""

292

293

async def resolve(self, hostname, port=0, family=0):

294

"""Resolve hostname using system resolver."""

295

296

async def close(self):

297

"""Close resolver resources."""

298

299

class ThreadedResolver:

300

def __init__(self, loop=None):

301

"""

302

Thread-based DNS resolver.

303

304

Parameters:

305

- loop: Event loop

306

"""

307

308

async def resolve(self, hostname, port=0, family=0):

309

"""Resolve hostname in thread pool."""

310

311

async def close(self):

312

"""Close resolver resources."""

313

```

314

315

### Helper Classes and Functions

316

317

Utility classes and functions for common operations and data structures.

318

319

```python { .api }

320

class ChainMapProxy:

321

def __init__(self, maps):

322

"""

323

Chain map proxy for nested dictionaries.

324

325

Parameters:

326

- maps: Sequence of dictionaries to chain

327

"""

328

329

def __getitem__(self, key):

330

"""Get item from chained maps."""

331

332

def __contains__(self, key):

333

"""Check if key exists in any map."""

334

335

def get(self, key, default=None):

336

"""Get item with default value."""

337

338

def keys(self):

339

"""Get all keys from chained maps."""

340

341

def values(self):

342

"""Get all values from chained maps."""

343

344

def items(self):

345

"""Get all items from chained maps."""

346

347

class ETag:

348

def __init__(self, value, is_weak=False):

349

"""

350

ETag header handling.

351

352

Parameters:

353

- value (str): ETag value

354

- is_weak (bool): Whether ETag is weak

355

"""

356

357

@property

358

def value(self):

359

"""ETag value."""

360

361

@property

362

def is_weak(self):

363

"""Whether ETag is weak."""

364

365

def __str__(self):

366

"""String representation of ETag."""

367

368

class Fingerprint:

369

def __init__(self, fingerprint):

370

"""

371

SSL certificate fingerprint handling.

372

373

Parameters:

374

- fingerprint (bytes): Certificate fingerprint

375

"""

376

377

def check(self, transport):

378

"""

379

Verify certificate fingerprint.

380

381

Parameters:

382

- transport: SSL transport

383

384

Raises:

385

ServerFingerprintMismatch: If fingerprint doesn't match

386

"""

387

388

class RequestInfo:

389

def __init__(self, url, method, headers, real_url=None):

390

"""

391

Request information container.

392

393

Parameters:

394

- url: Request URL

395

- method (str): HTTP method

396

- headers: Request headers

397

- real_url: Real URL after redirects

398

"""

399

400

@property

401

def url(self):

402

"""Request URL."""

403

404

@property

405

def method(self):

406

"""HTTP method."""

407

408

@property

409

def headers(self):

410

"""Request headers."""

411

412

@property

413

def real_url(self):

414

"""Real URL after redirects."""

415

```

416

417

### Compression Configuration

418

419

Compression backend configuration for optimized data processing.

420

421

```python { .api }

422

def set_zlib_backend(backend):

423

"""

424

Configure zlib backend for compression.

425

426

Parameters:

427

- backend (str): Backend name ('zlib' or 'brotli')

428

"""

429

```

430

431

### Gunicorn Worker Integration

432

433

Gunicorn worker classes for deploying aiohttp applications in production environments.

434

435

```python { .api }

436

class GunicornWebWorker:

437

"""Gunicorn worker for aiohttp applications."""

438

439

def __init__(self, age, ppid, sockets, app, log, cfg):

440

"""

441

Initialize Gunicorn worker.

442

443

Parameters:

444

- age: Worker age

445

- ppid: Parent process ID

446

- sockets: Server sockets

447

- app: WSGI application

448

- log: Logger instance

449

- cfg: Gunicorn configuration

450

"""

451

452

def init_process(self):

453

"""Initialize worker process."""

454

455

def run(self):

456

"""Run worker main loop."""

457

458

class GunicornUVLoopWebWorker(GunicornWebWorker):

459

"""Gunicorn worker with uvloop for enhanced performance."""

460

461

def init_process(self):

462

"""Initialize worker with uvloop."""

463

```

464

465

### HTTP Headers Module

466

467

Complete set of HTTP header constants and utilities.

468

469

```python { .api }

470

# HTTP method constants

471

METH_ANY = '*'

472

METH_CONNECT = 'CONNECT'

473

METH_HEAD = 'HEAD'

474

METH_GET = 'GET'

475

METH_DELETE = 'DELETE'

476

METH_OPTIONS = 'OPTIONS'

477

METH_PATCH = 'PATCH'

478

METH_POST = 'POST'

479

METH_PUT = 'PUT'

480

METH_TRACE = 'TRACE'

481

482

# Set of all HTTP methods

483

METH_ALL = frozenset([

484

METH_CONNECT, METH_HEAD, METH_GET, METH_DELETE,

485

METH_OPTIONS, METH_PATCH, METH_POST, METH_PUT, METH_TRACE

486

])

487

488

# HTTP header constants (istr objects for case-insensitive comparison)

489

ACCEPT = 'Accept'

490

ACCEPT_CHARSET = 'Accept-Charset'

491

ACCEPT_ENCODING = 'Accept-Encoding'

492

ACCEPT_LANGUAGE = 'Accept-Language'

493

ACCEPT_RANGES = 'Accept-Ranges'

494

ACCESS_CONTROL_ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials'

495

ACCESS_CONTROL_ALLOW_HEADERS = 'Access-Control-Allow-Headers'

496

ACCESS_CONTROL_ALLOW_METHODS = 'Access-Control-Allow-Methods'

497

ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin'

498

ACCESS_CONTROL_EXPOSE_HEADERS = 'Access-Control-Expose-Headers'

499

ACCESS_CONTROL_MAX_AGE = 'Access-Control-Max-Age'

500

ACCESS_CONTROL_REQUEST_HEADERS = 'Access-Control-Request-Headers'

501

ACCESS_CONTROL_REQUEST_METHOD = 'Access-Control-Request-Method'

502

AGE = 'Age'

503

ALLOW = 'Allow'

504

AUTHORIZATION = 'Authorization'

505

CACHE_CONTROL = 'Cache-Control'

506

CONNECTION = 'Connection'

507

CONTENT_DISPOSITION = 'Content-Disposition'

508

CONTENT_ENCODING = 'Content-Encoding'

509

CONTENT_LANGUAGE = 'Content-Language'

510

CONTENT_LENGTH = 'Content-Length'

511

CONTENT_LOCATION = 'Content-Location'

512

CONTENT_MD5 = 'Content-MD5'

513

CONTENT_RANGE = 'Content-Range'

514

CONTENT_TRANSFER_ENCODING = 'Content-Transfer-Encoding'

515

CONTENT_TYPE = 'Content-Type'

516

COOKIE = 'Cookie'

517

DATE = 'Date'

518

DESTINATION = 'Destination'

519

DIGEST = 'Digest'

520

ETAG = 'ETag'

521

EXPECT = 'Expect'

522

EXPIRES = 'Expires'

523

FORWARDED = 'Forwarded'

524

FROM = 'From'

525

HOST = 'Host'

526

IF_MATCH = 'If-Match'

527

IF_MODIFIED_SINCE = 'If-Modified-Since'

528

IF_NONE_MATCH = 'If-None-Match'

529

IF_RANGE = 'If-Range'

530

IF_UNMODIFIED_SINCE = 'If-Unmodified-Since'

531

LAST_MODIFIED = 'Last-Modified'

532

LINK = 'Link'

533

LOCATION = 'Location'

534

MAX_FORWARDS = 'Max-Forwards'

535

ORIGIN = 'Origin'

536

PRAGMA = 'Pragma'

537

PROXY_AUTHENTICATE = 'Proxy-Authenticate'

538

PROXY_AUTHORIZATION = 'Proxy-Authorization'

539

RANGE = 'Range'

540

REFERER = 'Referer'

541

RETRY_AFTER = 'Retry-After'

542

SEC_WEBSOCKET_ACCEPT = 'Sec-WebSocket-Accept'

543

SEC_WEBSOCKET_KEY = 'Sec-WebSocket-Key'

544

SEC_WEBSOCKET_KEY1 = 'Sec-WebSocket-Key1'

545

SEC_WEBSOCKET_KEY2 = 'Sec-WebSocket-Key2'

546

SEC_WEBSOCKET_ORIGIN = 'Sec-WebSocket-Origin'

547

SEC_WEBSOCKET_PROTOCOL = 'Sec-WebSocket-Protocol'

548

SEC_WEBSOCKET_VERSION = 'Sec-WebSocket-Version'

549

SERVER = 'Server'

550

SET_COOKIE = 'Set-Cookie'

551

TE = 'TE'

552

TRAILER = 'Trailer'

553

TRANSFER_ENCODING = 'Transfer-Encoding'

554

UPGRADE = 'Upgrade'

555

URI = 'URI'

556

USER_AGENT = 'User-Agent'

557

VARY = 'Vary'

558

VIA = 'Via'

559

WARNING = 'Warning'

560

WWW_AUTHENTICATE = 'WWW-Authenticate'

561

X_FORWARDED_FOR = 'X-Forwarded-For'

562

X_FORWARDED_HOST = 'X-Forwarded-Host'

563

X_FORWARDED_PROTO = 'X-Forwarded-Proto'

564

```

565

566

## Usage Examples

567

568

### Request Tracing for Performance Monitoring

569

570

```python

571

import aiohttp

572

import asyncio

573

import time

574

575

async def setup_tracing():

576

"""Setup comprehensive request tracing."""

577

trace_config = aiohttp.TraceConfig()

578

579

# Request lifecycle tracking

580

async def on_request_start(session, context, params):

581

context.start_time = time.time()

582

print(f"Starting request: {params.method} {params.url}")

583

584

async def on_request_end(session, context, params):

585

duration = time.time() - context.start_time

586

print(f"Request completed: {params.method} {params.url} "

587

f"({params.response.status}) in {duration:.3f}s")

588

589

async def on_request_exception(session, context, params):

590

duration = time.time() - context.start_time

591

print(f"Request failed: {params.method} {params.url} "

592

f"after {duration:.3f}s - {params.exception}")

593

594

# Connection tracking

595

async def on_connection_create_start(session, context, params):

596

print("Creating new connection...")

597

598

async def on_connection_create_end(session, context, params):

599

print("Connection created successfully")

600

601

async def on_connection_reuseconn(session, context, params):

602

print("Reusing existing connection")

603

604

# DNS tracking

605

async def on_dns_resolvehost_start(session, context, params):

606

print(f"Resolving DNS for {params.host}")

607

608

async def on_dns_resolvehost_end(session, context, params):

609

print(f"DNS resolved for {params.host}")

610

611

async def on_dns_cache_hit(session, context, params):

612

print(f"DNS cache hit for {params.host}")

613

614

# Register callbacks

615

trace_config.on_request_start(on_request_start)

616

trace_config.on_request_end(on_request_end)

617

trace_config.on_request_exception(on_request_exception)

618

trace_config.on_connection_create_start(on_connection_create_start)

619

trace_config.on_connection_create_end(on_connection_create_end)

620

trace_config.on_connection_reuseconn(on_connection_reuseconn)

621

trace_config.on_dns_resolvehost_start(on_dns_resolvehost_start)

622

trace_config.on_dns_resolvehost_end(on_dns_resolvehost_end)

623

trace_config.on_dns_cache_hit(on_dns_cache_hit)

624

625

return trace_config

626

627

async def traced_requests():

628

"""Make requests with tracing enabled."""

629

trace_config = await setup_tracing()

630

631

async with aiohttp.ClientSession(trace_configs=[trace_config]) as session:

632

# Make multiple requests to see tracing in action

633

urls = [

634

'https://httpbin.org/delay/1',

635

'https://httpbin.org/json',

636

'https://httpbin.org/status/200',

637

'https://httpbin.org/delay/1' # This should reuse connection

638

]

639

640

for url in urls:

641

try:

642

async with session.get(url) as response:

643

await response.read()

644

except Exception as e:

645

print(f"Request error: {e}")

646

647

# Run traced requests

648

asyncio.run(traced_requests())

649

```

650

651

### Custom DNS Resolver

652

653

```python

654

import aiohttp

655

import asyncio

656

import socket

657

658

class CustomResolver(aiohttp.AsyncResolver):

659

"""Custom DNS resolver with local overrides."""

660

661

def __init__(self, overrides=None, loop=None):

662

super().__init__(loop=loop)

663

self.overrides = overrides or {}

664

665

async def resolve(self, hostname, port=0, family=socket.AF_UNSPEC):

666

"""Resolve with local overrides."""

667

if hostname in self.overrides:

668

# Use override address

669

override_addr = self.overrides[hostname]

670

return [{

671

'hostname': hostname,

672

'host': override_addr,

673

'port': port,

674

'family': socket.AF_INET,

675

'proto': 0,

676

'flags': 0

677

}]

678

679

# Use default resolution

680

return await super().resolve(hostname, port, family)

681

682

async def use_custom_resolver():

683

"""Use custom DNS resolver."""

684

# Map hostnames to custom addresses

685

resolver = CustomResolver(overrides={

686

'api.local': '127.0.0.1',

687

'dev.example.com': '192.168.1.100'

688

})

689

690

connector = aiohttp.TCPConnector(resolver=resolver)

691

692

async with aiohttp.ClientSession(connector=connector) as session:

693

# This will resolve api.local to 127.0.0.1

694

try:

695

async with session.get('http://api.local:8080/test') as response:

696

return await response.text()

697

except aiohttp.ClientError as e:

698

print(f"Request failed: {e}")

699

700

asyncio.run(use_custom_resolver())

701

```

702

703

### Helper Utilities Usage

704

705

```python

706

from aiohttp.helpers import ChainMapProxy, ETag, BasicAuth

707

import aiohttp

708

709

def demonstrate_helpers():

710

"""Demonstrate utility helper classes."""

711

712

# ChainMapProxy for nested configuration

713

default_config = {'timeout': 30, 'retries': 3}

714

user_config = {'timeout': 60}

715

runtime_config = {'debug': True}

716

717

config = ChainMapProxy([runtime_config, user_config, default_config])

718

719

print(f"Timeout: {config['timeout']}") # 60 (from user_config)

720

print(f"Retries: {config['retries']}") # 3 (from default_config)

721

print(f"Debug: {config['debug']}") # True (from runtime_config)

722

723

# ETag handling

724

etag = ETag('abc123', is_weak=False)

725

print(f"ETag: {etag}") # "abc123"

726

727

weak_etag = ETag('def456', is_weak=True)

728

print(f"Weak ETag: {weak_etag}") # W/"def456"

729

730

# Basic authentication

731

auth = BasicAuth('username', 'password')

732

print(f"Auth login: {auth.login}")

733

print(f"Auth password: {auth.password}")

734

735

demonstrate_helpers()

736

```

737

738

### Production Deployment with Gunicorn

739

740

```python

741

# gunicorn_config.py - Gunicorn configuration file

742

import multiprocessing

743

744

# Server socket

745

bind = "0.0.0.0:8000"

746

backlog = 2048

747

748

# Worker processes

749

workers = multiprocessing.cpu_count() * 2 + 1

750

worker_class = "aiohttp.GunicornWebWorker"

751

worker_connections = 1000

752

max_requests = 1000

753

max_requests_jitter = 50

754

timeout = 30

755

keepalive = 2

756

757

# Logging

758

accesslog = "-"

759

errorlog = "-"

760

loglevel = "info"

761

access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'

762

763

# Process naming

764

proc_name = 'aiohttp_app'

765

766

# Server mechanics

767

daemon = False

768

pidfile = '/tmp/aiohttp_app.pid'

769

user = None

770

group = None

771

tmp_upload_dir = None

772

773

# SSL (if needed)

774

# keyfile = '/path/to/keyfile'

775

# certfile = '/path/to/certfile'

776

```

777

778

```python

779

# app.py - Application setup for Gunicorn

780

from aiohttp import web

781

import os

782

import logging

783

784

logging.basicConfig(level=logging.INFO)

785

logger = logging.getLogger(__name__)

786

787

async def health_check(request):

788

"""Health check endpoint."""

789

return web.json_response({'status': 'healthy'})

790

791

async def api_endpoint(request):

792

"""Sample API endpoint."""

793

return web.json_response({

794

'message': 'Hello from aiohttp!',

795

'worker_pid': os.getpid()

796

})

797

798

def create_app():

799

"""Create and configure the application."""

800

app = web.Application()

801

802

# Add routes

803

app.router.add_get('/health', health_check)

804

app.router.add_get('/api/hello', api_endpoint)

805

806

# Add middleware for logging

807

@web.middleware

808

async def logging_middleware(request, handler):

809

start_time = time.time()

810

response = await handler(request)

811

process_time = time.time() - start_time

812

logger.info(f"{request.method} {request.path} - {response.status} - {process_time:.3f}s")

813

return response

814

815

app.middlewares.append(logging_middleware)

816

817

# Startup/shutdown hooks

818

async def init_app(app):

819

logger.info("Application starting up...")

820

821

async def cleanup_app(app):

822

logger.info("Application shutting down...")

823

824

app.on_startup.append(init_app)

825

app.on_cleanup.append(cleanup_app)

826

827

return app

828

829

# For Gunicorn

830

app = create_app()

831

832

# For development

833

if __name__ == '__main__':

834

web.run_app(app, host='localhost', port=8000)

835

```

836

837

```bash

838

# Deploy with Gunicorn

839

gunicorn app:app -c gunicorn_config.py

840

841

# Or with uvloop for better performance

842

pip install uvloop

843

gunicorn app:app -c gunicorn_config.py --worker-class aiohttp.GunicornUVLoopWebWorker

844

```

845

846

### Compression Configuration

847

848

```python

849

import aiohttp

850

851

# Configure compression backend

852

aiohttp.set_zlib_backend('zlib') # Use standard zlib

853

# aiohttp.set_zlib_backend('brotli') # Use Brotli compression

854

855

async def compressed_request():

856

"""Make request with compression support."""

857

headers = {

858

'Accept-Encoding': 'gzip, deflate, br' # Support multiple encodings

859

}

860

861

async with aiohttp.ClientSession() as session:

862

async with session.get('https://httpbin.org/gzip',

863

headers=headers) as response:

864

# Response is automatically decompressed

865

data = await response.json()

866

return data

867

```