or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-wrappers.mdasync-integration.mdconfiguration.mdevents.mdindex.mdlogging.mdmiddleware.mdserver-execution.mdtypes.mdutilities.md

middleware.mddocs/

0

# Middleware

1

2

Built-in middleware components for common server functionality including WSGI adaptation, request routing, HTTPS redirection, and proxy header handling. These middleware classes provide reusable components for modifying request and response behavior.

3

4

## Capabilities

5

6

### WSGI Middleware for Asyncio

7

8

Middleware that enables WSGI application execution within asyncio event loops, handling the synchronous-to-asynchronous adaptation.

9

10

```python { .api }

11

class AsyncioWSGIMiddleware:

12

"""

13

WSGI middleware adapter for asyncio event loops.

14

15

Enables WSGI applications to run within asyncio-based servers

16

by providing the necessary synchronous execution context and

17

handling the translation between WSGI's blocking interface

18

and asyncio's non-blocking event loop.

19

"""

20

21

def __init__(self, wsgi_app: WSGIFramework, max_body_size: int = 16*1024*1024):

22

"""

23

Initialize asyncio WSGI middleware.

24

25

Args:

26

wsgi_app: WSGI application to wrap

27

max_body_size: Maximum request body size in bytes

28

"""

29

30

async def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable):

31

"""

32

Process request through WSGI application.

33

34

Args:

35

scope: ASGI scope dictionary

36

receive: ASGI receive callable

37

send: ASGI send callable

38

"""

39

```

40

41

### WSGI Middleware for Trio

42

43

Middleware that enables WSGI application execution within trio async frameworks, providing structured concurrency support.

44

45

```python { .api }

46

class TrioWSGIMiddleware:

47

"""

48

WSGI middleware adapter for trio async framework.

49

50

Enables WSGI applications to run within trio-based servers

51

with support for trio's structured concurrency model and

52

cancellation semantics.

53

"""

54

55

def __init__(self, wsgi_app: WSGIFramework, max_body_size: int = 16*1024*1024):

56

"""

57

Initialize trio WSGI middleware.

58

59

Args:

60

wsgi_app: WSGI application to wrap

61

max_body_size: Maximum request body size in bytes

62

"""

63

64

async def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable):

65

"""

66

Process request through WSGI application.

67

68

Args:

69

scope: ASGI scope dictionary

70

receive: ASGI receive callable

71

send: ASGI send callable

72

"""

73

```

74

75

### Dispatcher Middleware

76

77

Middleware for routing requests to different applications based on URL paths, enabling application composition and microservice architectures.

78

79

```python { .api }

80

class DispatcherMiddleware:

81

"""

82

Route requests to different applications based on path prefixes.

83

84

This is an alias for AsyncioDispatcherMiddleware for backward compatibility.

85

Enables mounting multiple applications at different URL paths,

86

similar to URL routing but at the application level.

87

"""

88

89

def __init__(self, mounts: dict[str, ASGIFramework]):

90

"""

91

Initialize dispatcher middleware.

92

93

Args:

94

mounts: Dictionary mapping path prefixes to ASGI applications

95

Format: {"/api": api_app, "/admin": admin_app}

96

"""

97

98

async def __call__(self, scope: Scope, receive: Callable, send: Callable):

99

"""

100

Route request to appropriate application.

101

102

Args:

103

scope: ASGI scope dictionary (path is examined for routing)

104

receive: ASGI receive callable

105

send: ASGI send callable

106

107

Routes based on longest matching path prefix.

108

"""

109

110

class AsyncioDispatcherMiddleware:

111

"""

112

Asyncio-specific dispatcher middleware for routing requests.

113

114

Routes requests to different applications based on path prefixes,

115

optimized for asyncio event loops.

116

"""

117

118

def __init__(self, mounts: dict[str, ASGIFramework]):

119

"""

120

Initialize asyncio dispatcher middleware.

121

122

Args:

123

mounts: Dictionary mapping path prefixes to ASGI applications

124

"""

125

126

async def __call__(self, scope: Scope, receive: Callable, send: Callable):

127

"""

128

Route request to appropriate application.

129

130

Args:

131

scope: ASGI scope dictionary

132

receive: ASGI receive callable

133

send: ASGI send callable

134

"""

135

136

class TrioDispatcherMiddleware:

137

"""

138

Trio-specific dispatcher middleware for routing requests.

139

140

Routes requests to different applications based on path prefixes,

141

optimized for trio async framework with structured concurrency.

142

"""

143

144

def __init__(self, mounts: dict[str, ASGIFramework]):

145

"""

146

Initialize trio dispatcher middleware.

147

148

Args:

149

mounts: Dictionary mapping path prefixes to ASGI applications

150

"""

151

152

async def __call__(self, scope: Scope, receive: Callable, send: Callable):

153

"""

154

Route request to appropriate application.

155

156

Args:

157

scope: ASGI scope dictionary

158

receive: ASGI receive callable

159

send: ASGI send callable

160

"""

161

```

162

163

### HTTP to HTTPS Redirect Middleware

164

165

Middleware that automatically redirects HTTP requests to their HTTPS equivalents, enforcing secure connections.

166

167

```python { .api }

168

class HTTPToHTTPSRedirectMiddleware:

169

"""

170

Redirect HTTP requests to HTTPS.

171

172

Automatically redirects all HTTP requests to their HTTPS

173

equivalents with a 301 permanent redirect. Useful for

174

enforcing HTTPS-only access to applications.

175

"""

176

177

def __init__(self, app: ASGIFramework | WSGIFramework, host: str | None = None):

178

"""

179

Initialize HTTPS redirect middleware.

180

181

Args:

182

app: Application to wrap (receives HTTPS requests)

183

host: Optional host to redirect to. If None, uses request host

184

"""

185

186

async def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable):

187

"""

188

Process request and redirect HTTP to HTTPS.

189

190

Args:

191

scope: ASGI scope dictionary (scheme is checked)

192

receive: ASGI receive callable

193

send: ASGI send callable

194

195

HTTP requests receive a 301 redirect to the HTTPS URL.

196

HTTPS requests are passed through to the wrapped application.

197

"""

198

```

199

200

### Proxy Fix Middleware

201

202

Middleware for handling proxy headers to correctly determine client information when running behind reverse proxies or load balancers.

203

204

```python { .api }

205

class ProxyFixMiddleware:

206

"""

207

Handle proxy headers for client information.

208

209

Corrects client IP addresses, schemes, and hosts when running

210

behind reverse proxies or load balancers by processing standard

211

proxy headers like X-Forwarded-For, X-Forwarded-Proto, etc.

212

"""

213

214

def __init__(

215

self,

216

app: ASGIFramework | WSGIFramework,

217

mode: Literal["legacy", "modern"] = "legacy",

218

trusted_hops: int = 1

219

):

220

"""

221

Initialize proxy fix middleware.

222

223

Args:

224

app: Application to wrap

225

mode: Header parsing mode ("legacy" or "modern")

226

trusted_hops: Number of proxy hops to trust

227

228

The trusted_hops parameter controls how many proxy entries

229

are trusted to prevent header spoofing from untrusted sources.

230

"""

231

232

async def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable):

233

"""

234

Process request and fix proxy headers.

235

236

Args:

237

scope: ASGI scope dictionary (headers are modified)

238

receive: ASGI receive callable

239

send: ASGI send callable

240

241

Modifies the scope to reflect the actual client information

242

based on trusted proxy headers.

243

"""

244

```

245

246

## Usage Examples

247

248

### WSGI Middleware Usage

249

250

```python

251

from hypercorn.middleware import AsyncioWSGIMiddleware

252

253

def wsgi_app(environ, start_response):

254

status = '200 OK'

255

headers = [('Content-Type', 'text/plain')]

256

start_response(status, headers)

257

return [b'Hello from WSGI middleware']

258

259

# Wrap WSGI app for asyncio

260

middleware = AsyncioWSGIMiddleware(wsgi_app, max_body_size=1024*1024)

261

262

# Use with Hypercorn

263

from hypercorn.config import Config

264

from hypercorn.asyncio import serve

265

266

config = Config()

267

asyncio.run(serve(middleware, config))

268

```

269

270

### Dispatcher Middleware

271

272

```python

273

from hypercorn.middleware import DispatcherMiddleware

274

275

# Define different applications

276

async def api_app(scope, receive, send):

277

await send({'type': 'http.response.start', 'status': 200})

278

await send({'type': 'http.response.body', 'body': b'API Response'})

279

280

async def admin_app(scope, receive, send):

281

await send({'type': 'http.response.start', 'status': 200})

282

await send({'type': 'http.response.body', 'body': b'Admin Panel'})

283

284

# Create dispatcher

285

dispatcher = DispatcherMiddleware({

286

'/api': api_app,

287

'/admin': admin_app,

288

'/': main_app # Default application

289

})

290

291

# Requests to /api/* go to api_app

292

# Requests to /admin/* go to admin_app

293

# All other requests go to main_app

294

```

295

296

### HTTPS Redirect Middleware

297

298

```python

299

from hypercorn.middleware import HTTPToHTTPSRedirectMiddleware

300

301

# Wrap application to enforce HTTPS

302

https_app = HTTPToHTTPSRedirectMiddleware(app)

303

304

# Or redirect to specific host

305

https_app = HTTPToHTTPSRedirectMiddleware(app, host="secure.example.com")

306

307

# HTTP requests get 301 redirect to HTTPS

308

# HTTPS requests are passed through to app

309

```

310

311

### Proxy Fix Middleware

312

313

```python

314

from hypercorn.middleware import ProxyFixMiddleware

315

316

# Basic proxy fix (trust 1 level of proxies)

317

proxy_app = ProxyFixMiddleware(app)

318

319

# Behind multiple proxies/load balancers

320

proxy_app = ProxyFixMiddleware(

321

app,

322

x_for=2, # Trust last 2 X-Forwarded-For entries

323

x_proto=1, # Trust last 1 X-Forwarded-Proto entry

324

x_host=1, # Trust last 1 X-Forwarded-Host entry

325

x_prefix=1 # Trust last 1 X-Forwarded-Prefix entry

326

)

327

328

# Now scope['client'] reflects actual client IP

329

# scope['scheme'] reflects actual scheme (http/https)

330

```

331

332

### Combining Middleware

333

334

```python

335

from hypercorn.middleware import (

336

ProxyFixMiddleware,

337

HTTPToHTTPSRedirectMiddleware,

338

DispatcherMiddleware

339

)

340

341

# Layer middleware (innermost to outermost)

342

app = my_asgi_app

343

344

# Fix proxy headers first

345

app = ProxyFixMiddleware(app, x_for=1, x_proto=1)

346

347

# Then enforce HTTPS

348

app = HTTPToHTTPSRedirectMiddleware(app)

349

350

# Finally, add routing if needed

351

apps = {'/api': api_app, '/': app}

352

final_app = DispatcherMiddleware(apps)

353

354

# Use final_app with Hypercorn

355

```

356

357

### Custom Middleware Pattern

358

359

```python

360

class CustomMiddleware:

361

def __init__(self, app):

362

self.app = app

363

364

async def __call__(self, scope, receive, send):

365

# Pre-processing

366

if scope['type'] == 'http':

367

# Modify request

368

scope['headers'].append([b'x-custom', b'value'])

369

370

# Call wrapped application

371

await self.app(scope, receive, self.send_wrapper(send))

372

373

def send_wrapper(self, send):

374

async def wrapped_send(message):

375

# Post-processing

376

if message['type'] == 'http.response.start':

377

# Modify response headers

378

message.setdefault('headers', [])

379

message['headers'].append([b'x-processed', b'true'])

380

await send(message)

381

return wrapped_send

382

383

# Usage

384

wrapped_app = CustomMiddleware(original_app)

385

```