or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compression.mdcore-middleware.mddjango-integration.mdindex.md

core-middleware.mddocs/

0

# Core WSGI Middleware

1

2

The WhiteNoise class provides the core static file serving functionality as WSGI middleware. It intercepts requests for static files and serves them directly, allowing your application to handle dynamic content while WhiteNoise efficiently serves static assets.

3

4

## Capabilities

5

6

### WhiteNoise Class

7

8

The main WSGI middleware class that serves static files with comprehensive HTTP feature support including compression, caching, range requests, and proper header handling.

9

10

```python { .api }

11

class WhiteNoise:

12

"""

13

WSGI middleware for serving static files.

14

15

Wraps a WSGI application to serve static files before passing requests

16

to the wrapped application. Supports compression, caching, and HTTP

17

best practices.

18

"""

19

20

def __init__(

21

self,

22

application,

23

root=None,

24

prefix=None,

25

*,

26

autorefresh: bool = False,

27

max_age: int | None = 60,

28

allow_all_origins: bool = True,

29

charset: str = "utf-8",

30

mimetypes: dict[str, str] | None = None,

31

add_headers_function: Callable[[Headers, str, str], None] | None = None,

32

index_file: str | bool | None = None,

33

immutable_file_test: Callable | str | None = None,

34

):

35

"""

36

Initialize WhiteNoise middleware.

37

38

Parameters:

39

- application: WSGI application to wrap

40

- root: Path to static files directory

41

- prefix: URL prefix for static files (e.g., '/static/')

42

- autorefresh: Re-scan filesystem on each request (development only)

43

- max_age: Cache-Control max-age in seconds (None disables caching)

44

- allow_all_origins: Add Access-Control-Allow-Origin: * header

45

- charset: Default charset for text files

46

- mimetypes: Additional MIME type mappings

47

- add_headers_function: Custom function to add headers

48

- index_file: Index file name (True for 'index.html')

49

- immutable_file_test: Function or regex to identify immutable files

50

"""

51

52

def __call__(self, environ, start_response):

53

"""

54

WSGI application interface.

55

56

Parameters:

57

- environ: WSGI environment dictionary

58

- start_response: WSGI start_response callable

59

60

Returns:

61

- WSGI response iterator

62

"""

63

64

def add_files(self, root, prefix=None):

65

"""

66

Add a directory of static files to serve.

67

68

Parameters:

69

- root: Absolute path to static files directory

70

- prefix: URL prefix for files (e.g., '/static/')

71

"""

72

73

@staticmethod

74

def serve(static_file, environ, start_response):

75

"""

76

Serve a static file (static method).

77

78

Parameters:

79

- static_file: StaticFile instance to serve

80

- environ: WSGI environment dictionary

81

- start_response: WSGI start_response callable

82

83

Returns:

84

- WSGI response iterator

85

"""

86

87

FOREVER: int # Cache duration constant (10 years in seconds)

88

```

89

90

### Usage Examples

91

92

#### Basic WSGI Integration

93

94

```python

95

from whitenoise import WhiteNoise

96

from my_app import application

97

98

# Wrap your WSGI application

99

application = WhiteNoise(application)

100

101

# Add static files with URL prefix

102

application.add_files('/var/www/static', prefix='/static/')

103

application.add_files('/var/www/media', prefix='/media/')

104

```

105

106

#### Development Configuration

107

108

```python

109

# Enable autorefresh for development (performance impact)

110

application = WhiteNoise(

111

application,

112

autorefresh=True,

113

max_age=0 # Disable caching for development

114

)

115

```

116

117

#### Production Configuration with Custom Headers

118

119

```python

120

def add_security_headers(headers, path, url):

121

"""Add security headers to static files."""

122

if url.endswith('.js'):

123

headers['X-Content-Type-Options'] = 'nosniff'

124

if url.endswith('.css'):

125

headers['X-Content-Type-Options'] = 'nosniff'

126

127

application = WhiteNoise(

128

application,

129

max_age=31536000, # 1 year cache for production

130

allow_all_origins=True,

131

add_headers_function=add_security_headers

132

)

133

```

134

135

#### Immutable File Detection

136

137

```python

138

import re

139

140

# Using regex pattern for versioned files

141

versioned_file_re = r'\.[0-9a-f]{8,32}\.'

142

143

application = WhiteNoise(

144

application,

145

immutable_file_test=versioned_file_re

146

)

147

148

# Using custom function

149

def is_immutable(path, url):

150

"""Check if file is immutable based on naming convention."""

151

return '.min.' in url or '.hash.' in url

152

153

application = WhiteNoise(

154

application,

155

immutable_file_test=is_immutable

156

)

157

```

158

159

### File Discovery and Caching

160

161

WhiteNoise operates in two modes for file discovery:

162

163

**Static Mode (Default)**: Files are scanned once at startup and stored in memory for fast lookup. Suitable for production environments.

164

165

**Autorefresh Mode**: Files are discovered on each request by scanning the filesystem. Only use for development as it has significant performance impact.

166

167

### HTTP Features

168

169

WhiteNoise implements comprehensive HTTP best practices:

170

171

- **Content Negotiation**: Automatically serves compressed variants (gzip, brotli) based on Accept-Encoding header

172

- **Conditional Requests**: Supports If-Modified-Since and If-None-Match headers for 304 responses

173

- **Range Requests**: Handles partial content requests for large files

174

- **CORS Support**: Configurable Cross-Origin Resource Sharing headers

175

- **Cache Headers**: Intelligent cache control with support for immutable files

176

177

### Static File Response System

178

179

Internal classes that handle HTTP responses and file serving, used by WhiteNoise for comprehensive static file delivery.

180

181

```python { .api }

182

class Response:

183

"""

184

HTTP response container for static file serving.

185

186

Represents the complete HTTP response including status, headers, and file content.

187

"""

188

189

def __init__(self, status, headers, file):

190

"""

191

Initialize HTTP response.

192

193

Parameters:

194

- status: HTTPStatus enum value

195

- headers: List of (name, value) header tuples

196

- file: File object or None for responses without body

197

"""

198

199

class StaticFile:

200

"""

201

Represents a static file with all its variants and metadata.

202

203

Handles compressed alternatives, conditional requests, range requests,

204

and proper HTTP header generation for efficient static file serving.

205

"""

206

207

def __init__(self, path, headers, encodings=None, stat_cache=None):

208

"""

209

Initialize static file representation.

210

211

Parameters:

212

- path: Absolute path to the file

213

- headers: List of (name, value) header tuples

214

- encodings: Dict mapping encodings to compressed file paths

215

- stat_cache: Optional stat cache for performance

216

"""

217

218

def get_response(self, method, request_headers):

219

"""

220

Generate HTTP response for the file.

221

222

Parameters:

223

- method: HTTP method (GET, HEAD, etc.)

224

- request_headers: Dict of request headers

225

226

Returns:

227

- Response: Complete HTTP response object

228

229

Handles conditional requests, range requests, content negotiation,

230

and proper HTTP status codes.

231

"""

232

233

class SlicedFile:

234

"""

235

File-like object for HTTP range requests.

236

237

Wraps a file to serve only a specific byte range, enabling

238

efficient partial content delivery for large files.

239

"""

240

241

def __init__(self, fileobj, start, end):

242

"""

243

Create sliced file for range request.

244

245

Parameters:

246

- fileobj: Source file object

247

- start: Starting byte position (inclusive)

248

- end: Ending byte position (inclusive)

249

"""

250

251

def read(self, size=-1):

252

"""

253

Read bytes respecting range limits.

254

255

Parameters:

256

- size: Maximum bytes to read (-1 for remaining)

257

258

Returns:

259

- bytes: File content within range limits

260

"""

261

262

class Redirect:

263

"""

264

HTTP redirect response for URL rewriting.

265

266

Used for index file handling and URL canonicalization.

267

"""

268

269

def __init__(self, location, headers=None):

270

"""

271

Create redirect response.

272

273

Parameters:

274

- location: Target URL for redirect

275

- headers: Optional additional headers

276

"""

277

278

def get_response(self, method, request_headers):

279

"""

280

Generate redirect response.

281

282

Parameters:

283

- method: HTTP method

284

- request_headers: Request headers dict

285

286

Returns:

287

- Response: 302 redirect response

288

"""

289

290

class FileEntry:

291

"""

292

File metadata container for stat caching.

293

294

Stores file path, size, and modification time for efficient

295

file system operations and HTTP header generation.

296

"""

297

298

def __init__(self, path, stat_cache=None):

299

"""

300

Create file entry with metadata.

301

302

Parameters:

303

- path: Absolute file path

304

- stat_cache: Optional stat cache for performance

305

"""

306

```

307

308

### Media Type Resolution

309

310

MIME type detection system for proper Content-Type header generation.

311

312

```python { .api }

313

class MediaTypes:

314

"""

315

MIME type resolver for static files.

316

317

Provides consistent media type detection across environments

318

using WhiteNoise's built-in type mappings with optional extensions.

319

"""

320

321

def __init__(self, *, extra_types: dict[str, str] | None = None):

322

"""

323

Initialize media type resolver.

324

325

Parameters:

326

- extra_types: Additional MIME type mappings to include

327

"""

328

329

def get_type(self, path: str) -> str:

330

"""

331

Determine MIME type for file path.

332

333

Parameters:

334

- path: File path to analyze

335

336

Returns:

337

- str: MIME type string (defaults to 'application/octet-stream')

338

339

Checks both filename and extension, with filename taking precedence

340

for special cases like 'apple-app-site-association'.

341

"""

342

```

343

344

### String Utilities

345

346

URL and path processing utilities for consistent handling across WhiteNoise.

347

348

```python { .api }

349

def decode_path_info(path_info):

350

"""

351

Decode URL path from WSGI PATH_INFO.

352

353

Parameters:

354

- path_info: Raw PATH_INFO string from WSGI environ

355

356

Returns:

357

- str: UTF-8 decoded path string

358

359

Handles UTF-8 URLs by undoing Python's implicit ISO-8859-1 decoding.

360

"""

361

362

def ensure_leading_trailing_slash(path):

363

"""

364

Normalize path to have leading and trailing slashes.

365

366

Parameters:

367

- path: Path string to normalize

368

369

Returns:

370

- str: Normalized path with leading/trailing slashes

371

372

Returns '/' for empty/None input, '/{path}/' for non-empty input.

373

"""

374

```

375

376

### Exception Classes

377

378

Specialized exceptions for static file handling and error reporting.

379

380

```python { .api }

381

class NotARegularFileError(Exception):

382

"""

383

Base exception for non-regular file encounters.

384

385

Raised when attempting to serve directories, devices, or other

386

non-regular file system objects.

387

"""

388

389

class MissingFileError(NotARegularFileError):

390

"""

391

Exception for missing or inaccessible files.

392

393

Raised when a requested file cannot be found or accessed.

394

"""

395

396

class IsDirectoryError(MissingFileError):

397

"""

398

Exception for directory access attempts.

399

400

Raised when attempting to serve a directory as a file.

401

"""

402

```

403

404

## Types

405

406

```python { .api }

407

from typing import Callable, Any

408

from wsgiref.headers import Headers

409

from http import HTTPStatus

410

411

# WSGI application type

412

WSGIApplication = Callable[[dict, Callable], Any]

413

414

# Custom header function type

415

AddHeadersFunction = Callable[[Headers, str, str], None]

416

417

# Immutable file test types

418

ImmutableFileTest = Callable[[str, str], bool]

419

ImmutableFilePattern = str

420

421

# HTTP response components

422

HTTPHeaders = list[tuple[str, str]]

423

RequestHeaders = dict[str, str]

424

```