The comprehensive WSGI web application library providing essential utilities and components for building Python web applications.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
The Request class wraps a WSGI environ dictionary, providing convenient access to all request data with automatic parsing and type conversion.
class Request:
def __init__(self, environ, populate_request=True, shallow=False):
"""
Create a new request wrapper.
Parameters:
- environ: WSGI environment dictionary
- populate_request: Whether to parse form data immediately
- shallow: Don't consume input stream for form parsing
"""
# URL and path information
method: str # HTTP method (GET, POST, etc.)
url: str # Complete URL
base_url: str # URL without query string
url_root: str # Protocol, host, and script root
path: str # Path portion of URL
script_root: str # SCRIPT_NAME from WSGI
query_string: str # Raw query string
# Request data access
args: MultiDict # Parsed query parameters
form: MultiDict # Parsed form data (POST/PUT)
files: MultiDict # Uploaded files as FileStorage objects
values: MultiDict # Combined args and form data
data: bytes # Raw request body
json: Any # Parsed JSON data (if Content-Type is JSON)
# Headers and metadata
headers: Headers # Request headers
cookies: dict # Request cookies
authorization: Optional[Authorization] # Authorization header
# User-Agent header accessible via headers.get('User-Agent')
# Accept headers for content negotiation
accept_mimetypes: MIMEAccept # Accept header
accept_charsets: CharsetAccept # Accept-Charset header
accept_encodings: Accept # Accept-Encoding header
accept_languages: LanguageAccept # Accept-Language header
# Conditional request headers
cache_control: RequestCacheControl # Cache-Control header
if_match: Optional[ETags] # If-Match header
if_none_match: Optional[ETags] # If-None-Match header
if_modified_since: Optional[datetime] # If-Modified-Since header
if_unmodified_since: Optional[datetime] # If-Unmodified-Since header
range: Optional[Range] # Range header
# Content information
content_type: Optional[str] # Content-Type header
content_length: Optional[int] # Content-Length header
mimetype: Optional[str] # MIME type from Content-Type
mimetype_params: dict # Parameters from Content-Type
# Request type checks
is_json: bool # True if Content-Type is JSON
is_secure: bool # True if request is over HTTPS
is_xhr: bool # True if X-Requested-With is XMLHttpRequest
# Client and server information
remote_addr: Optional[str] # Client IP address
remote_user: Optional[str] # Authenticated username
scheme: str # URL scheme (http/https)
host: str # Host header value
port: Optional[int] # Port number
def get_json(self, force=False, silent=False, cache=True):
"""
Parse request body as JSON.
Parameters:
- force: Parse even if Content-Type is not JSON
- silent: Return None instead of raising on parse errors
- cache: Cache parsed result
Returns:
Parsed JSON data or None
"""The Response class provides a high-level interface for creating HTTP responses with proper header management, cookie handling, and caching support.
class Response:
def __init__(self, response=None, status=None, headers=None, mimetype=None, content_type=None, direct_passthrough=False):
"""
Create a new response object.
Parameters:
- response: Response body (string, bytes, or iterable)
- status: HTTP status code or status line
- headers: Response headers (dict, list, or Headers object)
- mimetype: MIME type for Content-Type header
- content_type: Complete Content-Type header value
- direct_passthrough: Don't modify response body
"""
# Response data and status
data: bytes # Response body as bytes
status: str # Complete status line (e.g., "200 OK")
status_code: int # Status code number
headers: Headers # Response headers
# Content type information
mimetype: Optional[str] # MIME type portion
content_type: Optional[str] # Complete Content-Type header
content_length: Optional[int] # Content-Length header
# Caching headers
cache_control: ResponseCacheControl # Cache-Control header
expires: Optional[datetime] # Expires header
last_modified: Optional[datetime] # Last-Modified header
etag: Optional[str] # ETag header
# Other headers
www_authenticate: Optional[WWWAuthenticate] # WWW-Authenticate header
location: Optional[str] # Location header for redirects
def set_cookie(self, key, value="", max_age=None, expires=None, path="/", domain=None, secure=False, httponly=False, samesite=None):
"""
Set a cookie.
Parameters:
- key: Cookie name
- value: Cookie value
- max_age: Maximum age in seconds
- expires: Expiration datetime or timestamp
- path: Cookie path
- domain: Cookie domain
- secure: Only send over HTTPS
- httponly: Don't allow JavaScript access
- samesite: SameSite attribute ('Strict', 'Lax', or 'None')
"""
def delete_cookie(self, key, path="/", domain=None, secure=False, httponly=False, samesite=None):
"""
Delete a cookie by setting it to expire immediately.
Parameters:
- key: Cookie name to delete
- path: Cookie path (must match original)
- domain: Cookie domain (must match original)
- secure: Secure flag (must match original)
- httponly: HttpOnly flag (must match original)
- samesite: SameSite attribute (must match original)
"""
def set_etag(self, etag, weak=False):
"""
Set the ETag header.
Parameters:
- etag: ETag value
- weak: Whether this is a weak ETag
"""
def make_conditional(self, request_or_environ, accept_ranges=False, complete_length=None):
"""
Make response conditional based on request headers.
Handles If-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since
and Range headers automatically.
Parameters:
- request_or_environ: Request object or WSGI environ
- accept_ranges: Whether to accept Range requests
- complete_length: Total content length for partial content
Returns:
Response object (may be modified for 304/416 responses)
"""
def add_etag(self, overwrite=False, weak=False):
"""
Add an ETag header based on response content.
Parameters:
- overwrite: Replace existing ETag
- weak: Generate weak ETag
"""
def freeze(self, no_etag=False):
"""
Make response immutable and add ETag if missing.
Parameters:
- no_etag: Don't add ETag header
"""Helper for streaming responses with proper chunked encoding support.
class ResponseStream:
def __init__(self, response):
"""
Create a response stream wrapper.
Parameters:
- response: Response object to wrap
"""
def write(self, data):
"""
Write data to response stream.
Parameters:
- data: Data to write (string or bytes)
"""
def writelines(self, lines):
"""
Write multiple lines to response stream.
Parameters:
- lines: Iterable of lines to write
"""
def close(self):
"""Close the response stream."""from werkzeug.wrappers import Request, Response
def application(environ, start_response):
request = Request(environ)
# Access request data
method = request.method
path = request.path
user_agent = request.headers.get('User-Agent')
# Handle different content types
if request.is_json:
data = request.get_json()
response = Response(f"Received JSON: {data}")
elif request.method == 'POST':
form_data = request.form
response = Response(f"Form data: {dict(form_data)}")
else:
response = Response("Hello World!")
return response(environ, start_response)from werkzeug.wrappers import Request, Response
from werkzeug.utils import secure_filename
import os
def handle_upload(environ, start_response):
request = Request(environ)
if request.method == 'POST':
uploaded_file = request.files.get('file')
if uploaded_file and uploaded_file.filename:
filename = secure_filename(uploaded_file.filename)
upload_path = os.path.join('/uploads', filename)
uploaded_file.save(upload_path)
response = Response(f"File {filename} uploaded successfully")
else:
response = Response("No file uploaded", status=400)
else:
response = Response('''
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
''', mimetype='text/html')
return response(environ, start_response)from werkzeug.wrappers import Request, Response
import json
def api_endpoint(environ, start_response):
request = Request(environ)
data = {"message": "Hello", "status": "success"}
# Check what the client accepts
if request.accept_mimetypes.accept_json:
response = Response(
json.dumps(data),
mimetype='application/json'
)
elif request.accept_mimetypes.accept_html:
html = f"<h1>{data['message']}</h1><p>Status: {data['status']}</p>"
response = Response(html, mimetype='text/html')
else:
# Default to plain text
response = Response(f"{data['message']} - {data['status']}")
return response(environ, start_response)from werkzeug.wrappers import Request, Response
from werkzeug.http import http_date
from datetime import datetime
def cached_content(environ, start_response):
request = Request(environ)
# Create response with content
content = "This is cached content that changes infrequently"
response = Response(content)
# Set caching headers
response.last_modified = datetime(2023, 1, 1)
response.cache_control.max_age = 3600 # Cache for 1 hour
response.add_etag() # Generate ETag from content
# Make response conditional (handles 304 Not Modified)
response.make_conditional(request)
return response(environ, start_response)from werkzeug.wrappers import Request, Response
def session_example(environ, start_response):
request = Request(environ)
# Read existing session
session_id = request.cookies.get('session_id')
if session_id:
response = Response(f"Welcome back! Session: {session_id}")
else:
# Create new session
import uuid
new_session_id = str(uuid.uuid4())
response = Response(f"New session created: {new_session_id}")
# Set secure session cookie
response.set_cookie(
'session_id',
new_session_id,
max_age=3600, # 1 hour
secure=True, # HTTPS only
httponly=True, # No JavaScript access
samesite='Lax' # CSRF protection
)
return response(environ, start_response)Install with Tessl CLI
npx tessl i tessl/pypi-werkzeug