or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdcore-application.mddata-structures.mdexceptions-status.mdindex.mdmiddleware.mdrequests-responses.mdrouting.mdstatic-files.mdtesting.mdwebsockets.md

core-application.mddocs/

0

# Core Application

1

2

The Starlette application class is the central component that manages routing, middleware, lifecycle events, and configuration for your ASGI web application.

3

4

## Application Class

5

6

```python { .api }

7

from starlette.applications import Starlette

8

from starlette.routing import BaseRoute

9

from starlette.middleware import Middleware

10

from starlette.types import Lifespan

11

from typing import Sequence, Mapping, Callable, Any

12

13

class Starlette:

14

"""

15

Main application class for creating ASGI applications.

16

17

The Starlette application instance manages:

18

- Request routing

19

- Middleware stack

20

- Exception handling

21

- Lifecycle events (startup/shutdown)

22

- Application state

23

"""

24

25

def __init__(

26

self,

27

debug: bool = False,

28

routes: Sequence[BaseRoute] | None = None,

29

middleware: Sequence[Middleware] | None = None,

30

exception_handlers: Mapping[Any, Callable] | None = None,

31

on_startup: Sequence[Callable] | None = None,

32

on_shutdown: Sequence[Callable] | None = None,

33

lifespan: Lifespan[Any] | None = None,

34

) -> None:

35

"""

36

Initialize Starlette application.

37

38

Args:

39

debug: Enable debug mode with detailed error pages

40

routes: List of route definitions

41

middleware: List of middleware to apply

42

exception_handlers: Custom exception handlers

43

on_startup: Functions to run on application startup (deprecated)

44

on_shutdown: Functions to run on application shutdown (deprecated)

45

lifespan: Async context manager for application lifespan

46

"""

47

48

# Properties

49

@property

50

def routes(self) -> list[BaseRoute]:

51

"""List of application routes."""

52

53

@property

54

def router(self) -> Router:

55

"""Router instance handling request dispatch."""

56

57

@property

58

def state(self) -> State:

59

"""Application state object for sharing data."""

60

61

# Core methods

62

def url_path_for(self, name: str, /, **path_params: Any) -> URLPath:

63

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

64

65

def build_middleware_stack(self) -> ASGIApp:

66

"""Build the middleware stack around the application."""

67

68

# Route management

69

def mount(

70

self,

71

path: str,

72

app: ASGIApp,

73

name: str | None = None

74

) -> None:

75

"""Mount an ASGI application at the given path."""

76

77

def host(

78

self,

79

host: str,

80

app: ASGIApp,

81

name: str | None = None

82

) -> None:

83

"""Add host-based routing for the application."""

84

85

def add_route(

86

self,

87

path: str,

88

route: Callable[[Request], Awaitable[Response] | Response],

89

methods: list[str] | None = None,

90

name: str | None = None,

91

include_in_schema: bool = True,

92

) -> None:

93

"""Add an HTTP route to the application."""

94

95

def add_websocket_route(

96

self,

97

path: str,

98

route: Callable[[WebSocket], Awaitable[None]],

99

name: str | None = None,

100

) -> None:

101

"""Add a WebSocket route to the application."""

102

103

# Middleware management

104

def add_middleware(

105

self,

106

middleware_class: type,

107

*args: Any,

108

**kwargs: Any,

109

) -> None:

110

"""Add middleware to the application stack."""

111

112

# Exception handling

113

def add_exception_handler(

114

self,

115

exc_class_or_status_code: int | type[Exception],

116

handler: Callable,

117

) -> None:

118

"""Add custom exception handler."""

119

120

# Event handlers (deprecated - use lifespan instead)

121

def add_event_handler(

122

self,

123

event_type: str, # "startup" or "shutdown"

124

func: Callable,

125

) -> None:

126

"""Add event handler (deprecated)."""

127

128

# Deprecated decorators (will be removed in v1.0.0)

129

def exception_handler(

130

self,

131

exc_class_or_status_code: int | type[Exception]

132

) -> Callable:

133

"""Decorator for exception handlers (deprecated)."""

134

135

def route(

136

self,

137

path: str,

138

methods: list[str] | None = None,

139

name: str | None = None,

140

include_in_schema: bool = True,

141

) -> Callable:

142

"""Decorator for routes (deprecated)."""

143

144

def websocket_route(

145

self,

146

path: str,

147

name: str | None = None

148

) -> Callable:

149

"""Decorator for WebSocket routes (deprecated)."""

150

151

def middleware(self, middleware_type: str) -> Callable:

152

"""Decorator for middleware (deprecated)."""

153

```

154

155

## Basic Application Setup

156

157

### Simple Application

158

159

```python { .api }

160

from starlette.applications import Starlette

161

from starlette.responses import JSONResponse

162

from starlette.routing import Route

163

164

async def homepage(request):

165

return JSONResponse({"message": "Hello World"})

166

167

app = Starlette(

168

debug=True,

169

routes=[

170

Route("/", homepage),

171

]

172

)

173

```

174

175

### Application with Configuration

176

177

```python { .api }

178

from starlette.applications import Starlette

179

from starlette.config import Config

180

from starlette.middleware import Middleware

181

from starlette.middleware.cors import CORSMiddleware

182

from starlette.routing import Route

183

184

# Load configuration

185

config = Config(".env")

186

DEBUG = config("DEBUG", cast=bool, default=False)

187

188

# Configure middleware

189

middleware = [

190

Middleware(CORSMiddleware, allow_origins=["*"]),

191

]

192

193

# Configure exception handlers

194

def http_exception_handler(request, exc):

195

return JSONResponse(

196

{"error": exc.detail},

197

status_code=exc.status_code

198

)

199

200

exception_handlers = {

201

HTTPException: http_exception_handler,

202

}

203

204

# Create application

205

app = Starlette(

206

debug=DEBUG,

207

routes=routes,

208

middleware=middleware,

209

exception_handlers=exception_handlers,

210

)

211

```

212

213

## Application Lifecycle

214

215

### Startup and Shutdown Events (Deprecated)

216

217

```python { .api }

218

# Deprecated approach using on_startup/on_shutdown

219

async def startup():

220

print("Application is starting up...")

221

# Initialize database connections, load ML models, etc.

222

223

async def shutdown():

224

print("Application is shutting down...")

225

# Close database connections, cleanup resources, etc.

226

227

app = Starlette(

228

on_startup=[startup],

229

on_shutdown=[shutdown],

230

routes=routes,

231

)

232

```

233

234

### Modern Lifespan Management

235

236

```python { .api }

237

from contextlib import asynccontextmanager

238

from starlette.applications import Starlette

239

240

# Modern approach using lifespan context manager

241

@asynccontextmanager

242

async def lifespan(app: Starlette):

243

# Startup

244

print("Application starting up...")

245

# Initialize resources

246

app.state.database = await database.connect()

247

app.state.ml_models = await load_ml_models()

248

249

yield # Application runs here

250

251

# Shutdown

252

print("Application shutting down...")

253

# Cleanup resources

254

await app.state.database.disconnect()

255

await cleanup_ml_models(app.state.ml_models)

256

257

app = Starlette(

258

lifespan=lifespan,

259

routes=routes,

260

)

261

```

262

263

### Lifespan with Error Handling

264

265

```python { .api }

266

@asynccontextmanager

267

async def lifespan(app: Starlette):

268

# Startup phase

269

try:

270

# Initialize database

271

app.state.database = await database.connect()

272

273

# Initialize cache

274

app.state.cache = await cache.connect()

275

276

# Load configuration

277

app.state.config = await load_application_config()

278

279

print("Application startup complete")

280

281

except Exception as e:

282

print(f"Failed to start application: {e}")

283

raise

284

285

yield # Application is running

286

287

# Shutdown phase

288

try:

289

# Close connections gracefully

290

if hasattr(app.state, 'database'):

291

await app.state.database.disconnect()

292

293

if hasattr(app.state, 'cache'):

294

await app.state.cache.disconnect()

295

296

print("Application shutdown complete")

297

298

except Exception as e:

299

print(f"Error during shutdown: {e}")

300

301

app = Starlette(lifespan=lifespan, routes=routes)

302

```

303

304

## Application State

305

306

The application state object allows you to share data across your application.

307

308

```python { .api }

309

from starlette.datastructures import State

310

311

# Application state is automatically created

312

app = Starlette()

313

314

# Set state during lifespan or route handlers

315

@asynccontextmanager

316

async def lifespan(app: Starlette):

317

# Set application-level state

318

app.state.database = await connect_to_database()

319

app.state.config = load_config()

320

app.state.cache = {}

321

322

yield

323

324

await app.state.database.disconnect()

325

326

# Access state in route handlers

327

async def get_users(request):

328

database = request.app.state.database

329

users = await database.fetch_all("SELECT * FROM users")

330

return JSONResponse([dict(user) for user in users])

331

332

# Access state in middleware

333

class DatabaseMiddleware:

334

def __init__(self, app):

335

self.app = app

336

337

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

338

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

339

# Access app state

340

database = scope["app"].state.database

341

# Add to request scope

342

scope["database"] = database

343

344

await self.app(scope, receive, send)

345

```

346

347

## URL Generation

348

349

```python { .api }

350

from starlette.routing import Route

351

352

# Named routes for URL generation

353

routes = [

354

Route("/", homepage, name="home"),

355

Route("/users/{user_id}", user_detail, name="user_detail"),

356

Route("/api/users/{user_id}/posts/{post_id}", post_detail, name="post_detail"),

357

]

358

359

app = Starlette(routes=routes)

360

361

# Generate URLs from application

362

home_url = app.url_path_for("home") # "/"

363

user_url = app.url_path_for("user_detail", user_id=123) # "/users/123"

364

post_url = app.url_path_for(

365

"post_detail",

366

user_id=123,

367

post_id=456

368

) # "/api/users/123/posts/456"

369

370

# Generate URLs in request handlers

371

async def some_endpoint(request):

372

# Access url_path_for through request

373

user_url = request.url_for("user_detail", user_id=123)

374

375

return JSONResponse({

376

"user_profile_url": str(user_url),

377

"home_url": str(request.url_for("home"))

378

})

379

```

380

381

## Dynamic Route Management

382

383

```python { .api }

384

# Add routes dynamically after application creation

385

app = Starlette()

386

387

# Add individual routes

388

app.add_route("/health", health_check, methods=["GET"])

389

app.add_websocket_route("/ws", websocket_endpoint)

390

391

# Mount sub-applications

392

from starlette.staticfiles import StaticFiles

393

app.mount("/static", StaticFiles(directory="static"), name="static")

394

395

# Mount API sub-application

396

api_app = Starlette(routes=api_routes)

397

app.mount("/api/v1", api_app, name="api_v1")

398

399

# Host-based routing

400

admin_app = Starlette(routes=admin_routes)

401

app.host("admin.example.com", admin_app, name="admin")

402

```

403

404

## Exception Handling

405

406

```python { .api }

407

from starlette.exceptions import HTTPException

408

from starlette.responses import JSONResponse, PlainTextResponse

409

410

# Global exception handlers

411

async def http_exception_handler(request, exc):

412

return JSONResponse(

413

{"error": exc.detail},

414

status_code=exc.status_code,

415

headers=exc.headers,

416

)

417

418

async def validation_exception_handler(request, exc):

419

return JSONResponse(

420

{"error": "Validation failed", "details": str(exc)},

421

status_code=422,

422

)

423

424

async def generic_exception_handler(request, exc):

425

return PlainTextResponse(

426

"Internal server error",

427

status_code=500,

428

)

429

430

# Configure exception handlers

431

exception_handlers = {

432

HTTPException: http_exception_handler,

433

ValueError: validation_exception_handler,

434

500: generic_exception_handler, # By status code

435

}

436

437

app = Starlette(

438

exception_handlers=exception_handlers,

439

routes=routes,

440

)

441

442

# Add exception handlers dynamically

443

app.add_exception_handler(KeyError, key_error_handler)

444

app.add_exception_handler(404, not_found_handler)

445

```

446

447

## Debug Mode

448

449

```python { .api }

450

# Enable debug mode for development

451

app = Starlette(debug=True, routes=routes)

452

453

# Debug mode provides:

454

# - Detailed error pages with stack traces

455

# - Automatic reloading on code changes (with --reload)

456

# - More verbose logging

457

458

# Control debug mode with environment variables

459

from starlette.config import Config

460

461

config = Config()

462

DEBUG = config("DEBUG", cast=bool, default=False)

463

464

app = Starlette(debug=DEBUG, routes=routes)

465

```

466

467

## Application Composition

468

469

```python { .api }

470

# Compose applications from multiple modules

471

from .api import api_app

472

from .admin import admin_app

473

from .auth import auth_app

474

475

# Main application

476

app = Starlette()

477

478

# Mount sub-applications

479

app.mount("/api", api_app, name="api")

480

app.mount("/admin", admin_app, name="admin")

481

app.mount("/auth", auth_app, name="auth")

482

483

# Add global middleware

484

app.add_middleware(CORSMiddleware, allow_origins=["*"])

485

app.add_middleware(GZipMiddleware, minimum_size=1000)

486

487

# Add global routes

488

app.add_route("/", homepage, name="home")

489

app.add_route("/health", health_check, name="health")

490

491

# Static files

492

app.mount("/static", StaticFiles(directory="static"), name="static")

493

```

494

495

## Testing Applications

496

497

```python { .api }

498

from starlette.testclient import TestClient

499

500

# Test application with lifespan

501

def test_application():

502

with TestClient(app) as client:

503

# Lifespan events are executed

504

response = client.get("/")

505

assert response.status_code == 200

506

507

# Test URL generation

508

assert client.app.url_path_for("home") == "/"

509

510

# Test application state

511

assert hasattr(client.app.state, "database")

512

513

# Test application without lifespan

514

def test_routes_only():

515

client = TestClient(app)

516

response = client.get("/health")

517

assert response.status_code == 200

518

client.close() # Manual cleanup when not using context manager

519

```

520

521

The Starlette application class provides a flexible foundation for building web applications with proper lifecycle management, state sharing, and composable architecture.