or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-structures.mddev-server.mdexceptions.mdhttp-utilities.mdindex.mdmiddleware.mdrequest-response.mdrouting.mdsecurity.mdtesting.mdurl-wsgi-utils.md

request-response.mddocs/

0

# Request and Response Handling

1

2

Complete WSGI request and response wrappers providing high-level access to HTTP data including headers, cookies, form data, file uploads, content negotiation, and conditional requests. These classes form the foundation of Werkzeug's web development capabilities.

3

4

## Capabilities

5

6

### Request Object

7

8

The Request class wraps a WSGI environ dictionary, providing convenient access to all request data with automatic parsing and type conversion.

9

10

```python { .api }

11

class Request:

12

def __init__(self, environ, populate_request=True, shallow=False):

13

"""

14

Create a new request wrapper.

15

16

Parameters:

17

- environ: WSGI environment dictionary

18

- populate_request: Whether to parse form data immediately

19

- shallow: Don't consume input stream for form parsing

20

"""

21

22

# URL and path information

23

method: str # HTTP method (GET, POST, etc.)

24

url: str # Complete URL

25

base_url: str # URL without query string

26

url_root: str # Protocol, host, and script root

27

path: str # Path portion of URL

28

script_root: str # SCRIPT_NAME from WSGI

29

query_string: str # Raw query string

30

31

# Request data access

32

args: MultiDict # Parsed query parameters

33

form: MultiDict # Parsed form data (POST/PUT)

34

files: MultiDict # Uploaded files as FileStorage objects

35

values: MultiDict # Combined args and form data

36

data: bytes # Raw request body

37

json: Any # Parsed JSON data (if Content-Type is JSON)

38

39

# Headers and metadata

40

headers: Headers # Request headers

41

cookies: dict # Request cookies

42

authorization: Optional[Authorization] # Authorization header

43

# User-Agent header accessible via headers.get('User-Agent')

44

45

# Accept headers for content negotiation

46

accept_mimetypes: MIMEAccept # Accept header

47

accept_charsets: CharsetAccept # Accept-Charset header

48

accept_encodings: Accept # Accept-Encoding header

49

accept_languages: LanguageAccept # Accept-Language header

50

51

# Conditional request headers

52

cache_control: RequestCacheControl # Cache-Control header

53

if_match: Optional[ETags] # If-Match header

54

if_none_match: Optional[ETags] # If-None-Match header

55

if_modified_since: Optional[datetime] # If-Modified-Since header

56

if_unmodified_since: Optional[datetime] # If-Unmodified-Since header

57

range: Optional[Range] # Range header

58

59

# Content information

60

content_type: Optional[str] # Content-Type header

61

content_length: Optional[int] # Content-Length header

62

mimetype: Optional[str] # MIME type from Content-Type

63

mimetype_params: dict # Parameters from Content-Type

64

65

# Request type checks

66

is_json: bool # True if Content-Type is JSON

67

is_secure: bool # True if request is over HTTPS

68

is_xhr: bool # True if X-Requested-With is XMLHttpRequest

69

70

# Client and server information

71

remote_addr: Optional[str] # Client IP address

72

remote_user: Optional[str] # Authenticated username

73

scheme: str # URL scheme (http/https)

74

host: str # Host header value

75

port: Optional[int] # Port number

76

77

def get_json(self, force=False, silent=False, cache=True):

78

"""

79

Parse request body as JSON.

80

81

Parameters:

82

- force: Parse even if Content-Type is not JSON

83

- silent: Return None instead of raising on parse errors

84

- cache: Cache parsed result

85

86

Returns:

87

Parsed JSON data or None

88

"""

89

```

90

91

### Response Object

92

93

The Response class provides a high-level interface for creating HTTP responses with proper header management, cookie handling, and caching support.

94

95

```python { .api }

96

class Response:

97

def __init__(self, response=None, status=None, headers=None, mimetype=None, content_type=None, direct_passthrough=False):

98

"""

99

Create a new response object.

100

101

Parameters:

102

- response: Response body (string, bytes, or iterable)

103

- status: HTTP status code or status line

104

- headers: Response headers (dict, list, or Headers object)

105

- mimetype: MIME type for Content-Type header

106

- content_type: Complete Content-Type header value

107

- direct_passthrough: Don't modify response body

108

"""

109

110

# Response data and status

111

data: bytes # Response body as bytes

112

status: str # Complete status line (e.g., "200 OK")

113

status_code: int # Status code number

114

headers: Headers # Response headers

115

116

# Content type information

117

mimetype: Optional[str] # MIME type portion

118

content_type: Optional[str] # Complete Content-Type header

119

content_length: Optional[int] # Content-Length header

120

121

# Caching headers

122

cache_control: ResponseCacheControl # Cache-Control header

123

expires: Optional[datetime] # Expires header

124

last_modified: Optional[datetime] # Last-Modified header

125

etag: Optional[str] # ETag header

126

127

# Other headers

128

www_authenticate: Optional[WWWAuthenticate] # WWW-Authenticate header

129

location: Optional[str] # Location header for redirects

130

131

def set_cookie(self, key, value="", max_age=None, expires=None, path="/", domain=None, secure=False, httponly=False, samesite=None):

132

"""

133

Set a cookie.

134

135

Parameters:

136

- key: Cookie name

137

- value: Cookie value

138

- max_age: Maximum age in seconds

139

- expires: Expiration datetime or timestamp

140

- path: Cookie path

141

- domain: Cookie domain

142

- secure: Only send over HTTPS

143

- httponly: Don't allow JavaScript access

144

- samesite: SameSite attribute ('Strict', 'Lax', or 'None')

145

"""

146

147

def delete_cookie(self, key, path="/", domain=None, secure=False, httponly=False, samesite=None):

148

"""

149

Delete a cookie by setting it to expire immediately.

150

151

Parameters:

152

- key: Cookie name to delete

153

- path: Cookie path (must match original)

154

- domain: Cookie domain (must match original)

155

- secure: Secure flag (must match original)

156

- httponly: HttpOnly flag (must match original)

157

- samesite: SameSite attribute (must match original)

158

"""

159

160

def set_etag(self, etag, weak=False):

161

"""

162

Set the ETag header.

163

164

Parameters:

165

- etag: ETag value

166

- weak: Whether this is a weak ETag

167

"""

168

169

def make_conditional(self, request_or_environ, accept_ranges=False, complete_length=None):

170

"""

171

Make response conditional based on request headers.

172

173

Handles If-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since

174

and Range headers automatically.

175

176

Parameters:

177

- request_or_environ: Request object or WSGI environ

178

- accept_ranges: Whether to accept Range requests

179

- complete_length: Total content length for partial content

180

181

Returns:

182

Response object (may be modified for 304/416 responses)

183

"""

184

185

def add_etag(self, overwrite=False, weak=False):

186

"""

187

Add an ETag header based on response content.

188

189

Parameters:

190

- overwrite: Replace existing ETag

191

- weak: Generate weak ETag

192

"""

193

194

def freeze(self, no_etag=False):

195

"""

196

Make response immutable and add ETag if missing.

197

198

Parameters:

199

- no_etag: Don't add ETag header

200

"""

201

```

202

203

### Response Stream

204

205

Helper for streaming responses with proper chunked encoding support.

206

207

```python { .api }

208

class ResponseStream:

209

def __init__(self, response):

210

"""

211

Create a response stream wrapper.

212

213

Parameters:

214

- response: Response object to wrap

215

"""

216

217

def write(self, data):

218

"""

219

Write data to response stream.

220

221

Parameters:

222

- data: Data to write (string or bytes)

223

"""

224

225

def writelines(self, lines):

226

"""

227

Write multiple lines to response stream.

228

229

Parameters:

230

- lines: Iterable of lines to write

231

"""

232

233

def close(self):

234

"""Close the response stream."""

235

```

236

237

## Usage Examples

238

239

### Basic Request Handling

240

241

```python

242

from werkzeug.wrappers import Request, Response

243

244

def application(environ, start_response):

245

request = Request(environ)

246

247

# Access request data

248

method = request.method

249

path = request.path

250

user_agent = request.headers.get('User-Agent')

251

252

# Handle different content types

253

if request.is_json:

254

data = request.get_json()

255

response = Response(f"Received JSON: {data}")

256

elif request.method == 'POST':

257

form_data = request.form

258

response = Response(f"Form data: {dict(form_data)}")

259

else:

260

response = Response("Hello World!")

261

262

return response(environ, start_response)

263

```

264

265

### File Upload Handling

266

267

```python

268

from werkzeug.wrappers import Request, Response

269

from werkzeug.utils import secure_filename

270

import os

271

272

def handle_upload(environ, start_response):

273

request = Request(environ)

274

275

if request.method == 'POST':

276

uploaded_file = request.files.get('file')

277

if uploaded_file and uploaded_file.filename:

278

filename = secure_filename(uploaded_file.filename)

279

upload_path = os.path.join('/uploads', filename)

280

uploaded_file.save(upload_path)

281

response = Response(f"File {filename} uploaded successfully")

282

else:

283

response = Response("No file uploaded", status=400)

284

else:

285

response = Response('''

286

<form method="POST" enctype="multipart/form-data">

287

<input type="file" name="file">

288

<input type="submit" value="Upload">

289

</form>

290

''', mimetype='text/html')

291

292

return response(environ, start_response)

293

```

294

295

### Content Negotiation

296

297

```python

298

from werkzeug.wrappers import Request, Response

299

import json

300

301

def api_endpoint(environ, start_response):

302

request = Request(environ)

303

304

data = {"message": "Hello", "status": "success"}

305

306

# Check what the client accepts

307

if request.accept_mimetypes.accept_json:

308

response = Response(

309

json.dumps(data),

310

mimetype='application/json'

311

)

312

elif request.accept_mimetypes.accept_html:

313

html = f"<h1>{data['message']}</h1><p>Status: {data['status']}</p>"

314

response = Response(html, mimetype='text/html')

315

else:

316

# Default to plain text

317

response = Response(f"{data['message']} - {data['status']}")

318

319

return response(environ, start_response)

320

```

321

322

### Conditional Responses and Caching

323

324

```python

325

from werkzeug.wrappers import Request, Response

326

from werkzeug.http import http_date

327

from datetime import datetime

328

329

def cached_content(environ, start_response):

330

request = Request(environ)

331

332

# Create response with content

333

content = "This is cached content that changes infrequently"

334

response = Response(content)

335

336

# Set caching headers

337

response.last_modified = datetime(2023, 1, 1)

338

response.cache_control.max_age = 3600 # Cache for 1 hour

339

response.add_etag() # Generate ETag from content

340

341

# Make response conditional (handles 304 Not Modified)

342

response.make_conditional(request)

343

344

return response(environ, start_response)

345

```

346

347

### Cookie Handling

348

349

```python

350

from werkzeug.wrappers import Request, Response

351

352

def session_example(environ, start_response):

353

request = Request(environ)

354

355

# Read existing session

356

session_id = request.cookies.get('session_id')

357

358

if session_id:

359

response = Response(f"Welcome back! Session: {session_id}")

360

else:

361

# Create new session

362

import uuid

363

new_session_id = str(uuid.uuid4())

364

response = Response(f"New session created: {new_session_id}")

365

366

# Set secure session cookie

367

response.set_cookie(

368

'session_id',

369

new_session_id,

370

max_age=3600, # 1 hour

371

secure=True, # HTTPS only

372

httponly=True, # No JavaScript access

373

samesite='Lax' # CSRF protection

374

)

375

376

return response(environ, start_response)

377

```