Fast and simple WSGI micro web-framework for small web applications with no dependencies other than the Python Standard Library.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Request object providing access to HTTP request data including headers, query parameters, form data, file uploads, cookies, and JSON data.
The global request object provides access to all HTTP request data for the current request.
request: LocalRequest
"""Global thread-local request instance available in route handlers."""Access HTTP request metadata and content.
class BaseRequest:
@property
def method(self) -> str:
"""HTTP method (GET, POST, PUT, DELETE, etc.)."""
@property
def path(self) -> str:
"""Request path without query string."""
@property
def fullpath(self) -> str:
"""Request path with query string."""
@property
def url(self) -> str:
"""Full request URL."""
@property
def urlparts(self) -> SplitResult:
"""Parsed URL components."""
@property
def environ(self) -> dict:
"""WSGI environ dictionary."""
@property
def route(self) -> Route:
"""The Route object that matched this request."""Access URL query string parameters.
class BaseRequest:
@property
def query(self) -> FormsDict:
"""Query string parameters as FormsDict."""
@property
def query_string(self) -> str:
"""Raw query string."""Usage:
# URL: /search?q=python&page=2
@route('/search')
def search():
query = request.query.q # 'python'
page = request.query.get('page', 1, type=int) # 2
return f'Searching for: {query}, page: {page}'Access form data from POST requests.
class BaseRequest:
@property
def forms(self) -> FormsDict:
"""Form data from POST request body."""
@property
def params(self) -> FormsDict:
"""Combined query parameters and form data."""Usage:
@route('/login', method='POST')
def login():
username = request.forms.get('username')
password = request.forms.get('password')
return f'Login attempt: {username}'Handle file uploads in multipart forms.
class BaseRequest:
@property
def files(self) -> FormsDict:
"""Uploaded files as FileUpload objects."""
class FileUpload:
@property
def name(self) -> str:
"""Form field name."""
@property
def filename(self) -> str:
"""Original filename."""
@property
def file(self):
"""File-like object for reading."""
@property
def headers(self) -> HeaderDict:
"""Upload headers."""
def save(self, destination, overwrite=False, chunk_size=65536):
"""
Save uploaded file to destination.
Parameters:
- destination: str, file path or file-like object
- overwrite: bool, whether to overwrite existing files
- chunk_size: int, read chunk size in bytes
"""Usage:
@route('/upload', method='POST')
def upload():
upload = request.files.get('file')
if upload:
upload.save('/uploads/' + upload.filename)
return f'Uploaded: {upload.filename}'
return 'No file uploaded'Access JSON request body data.
class BaseRequest:
@property
def json(self) -> Any:
"""
Parsed JSON request body.
Returns:
Any: parsed JSON data or None if not JSON or parse error
"""Usage:
@route('/api/data', method='POST')
def api_data():
data = request.json
if data:
return {'received': data}
return {'error': 'No JSON data'}Access HTTP request headers.
class BaseRequest:
@property
def headers(self) -> HeaderDict:
"""Request headers as case-insensitive dictionary."""
def get_header(self, name, default=None):
"""
Get request header value.
Parameters:
- name: str, header name (case-insensitive)
- default: any, default value if header not found
Returns:
str or default: header value
"""Usage:
@route('/api/test')
def test():
auth = request.get_header('Authorization')
content_type = request.headers.get('Content-Type')
user_agent = request.get_header('User-Agent', 'Unknown')
return {'auth': auth, 'content_type': content_type, 'user_agent': user_agent}Access request cookies.
class BaseRequest:
@property
def cookies(self) -> SimpleCookie:
"""Request cookies as SimpleCookie object."""
def get_cookie(self, key, default=None, secret=None, digestmod=hashlib.sha256):
"""
Get cookie value, optionally validating signed cookies.
Parameters:
- key: str, cookie name
- default: any, default value if cookie not found
- secret: str, secret for signed cookie validation
- digestmod: hashlib algorithm for signature verification
Returns:
str or default: cookie value
"""Usage:
@route('/profile')
def profile():
user_id = request.get_cookie('user_id')
session = request.get_cookie('session', secret='my-secret')
if user_id and session:
return f'User: {user_id}'
return 'Not logged in'Access raw request body and content information.
class BaseRequest:
@property
def body(self) -> bytes:
"""Raw request body as bytes."""
@property
def content_length(self) -> int:
"""Content-Length header value."""
@property
def content_type(self) -> str:
"""Content-Type header value."""
@property
def is_xhr(self) -> bool:
"""True if request is XMLHttpRequest (AJAX)."""
@property
def is_ajax(self) -> bool:
"""Alias for is_xhr."""Additional request context and utilities.
class BaseRequest:
@property
def script_name(self) -> str:
"""SCRIPT_NAME from WSGI environ."""
@property
def path_info(self) -> str:
"""PATH_INFO from WSGI environ."""
@property
def auth(self) -> tuple:
"""HTTP Basic Auth (username, password) or None."""
def get(self, value, default=None):
"""
Get value from WSGI environ.
Parameters:
- value: str, WSGI environ key
- default: any, default value
Returns:
any: environ value or default
"""Dictionary for form data with multiple values per key and type conversion.
class FormsDict(MultiDict):
def get(self, key, default=None, index=-1, type=None):
"""
Get form value with optional type conversion.
Parameters:
- key: str, form field name
- default: any, default value if not found
- index: int, value index for multi-value fields (-1 for last)
- type: callable, type conversion function
Returns:
any: form value, converted if type specified
"""
def getall(self, key):
"""Get all values for a form field as list."""
def getunicode(self, name, default=None, encoding=None):
"""
Get form value as unicode string.
Parameters:
- name: str, form field name
- default: any, default value
- encoding: str, character encoding
Returns:
str: unicode form value
"""Base dictionary class allowing multiple values per key.
class MultiDict:
def get(self, key, default=None, index=-1, type=None):
"""Get value with optional type conversion."""
def getall(self, key):
"""Get all values for key as list."""
def append(self, key, value):
"""Append value to key."""
def replace(self, key, value):
"""Replace all values for key with single value."""
def getlist(self, key):
"""Alias for getall."""Case-insensitive dictionary for HTTP headers.
class HeaderDict(MultiDict):
"""Case-insensitive MultiDict for HTTP headers."""
def get(self, key, default=None, index=-1):
"""Get header value (case-insensitive key)."""
def getall(self, key):
"""Get all header values (case-insensitive key)."""Install with Tessl CLI
npx tessl i tessl/pypi-bottle