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
Response object for setting HTTP response properties including status codes, headers, cookies, content type, and response body handling.
The global response object allows modification of HTTP response properties.
response: LocalResponse
"""Global thread-local response instance available in route handlers."""Set basic HTTP response properties.
class BaseResponse:
@property
def status(self) -> int:
"""HTTP status code (200, 404, 500, etc.)."""
@status.setter
def status(self, value: int):
"""Set HTTP status code."""
@property
def status_line(self) -> str:
"""Full HTTP status line (e.g., '200 OK')."""
@property
def status_code(self) -> int:
"""Alias for status property."""
@property
def headers(self) -> HeaderDict:
"""Response headers as HeaderDict."""
@property
def headerlist(self) -> list:
"""Response headers as list of (name, value) tuples."""
@property
def content_type(self) -> str:
"""Content-Type header value."""
@content_type.setter
def content_type(self, value: str):
"""Set Content-Type header."""
@property
def content_length(self) -> int:
"""Content-Length header value."""
@content_length.setter
def content_length(self, value: int):
"""Set Content-Length header."""
@property
def charset(self) -> str:
"""Character encoding from Content-Type."""
@charset.setter
def charset(self, value: str):
"""Set character encoding in Content-Type."""Add, set, and retrieve response headers.
class BaseResponse:
def set_header(self, name, value):
"""
Set response header, replacing any existing values.
Parameters:
- name: str, header name
- value: str, header value
"""
def add_header(self, name, value):
"""
Add response header, preserving existing values.
Parameters:
- name: str, header name
- value: str, header value
"""
def get_header(self, name, default=None):
"""
Get response header value.
Parameters:
- name: str, header name (case-insensitive)
- default: any, default value if header not found
Returns:
str or default: header value
"""
def iter_headers(self):
"""Iterate over all response headers as (name, value) tuples."""Usage:
@route('/api/data')
def api_data():
response.content_type = 'application/json'
response.set_header('X-API-Version', '1.0')
response.add_header('X-Custom', 'value1')
response.add_header('X-Custom', 'value2') # Multiple values
return '{"data": "example"}'Set and delete response cookies with various options.
class BaseResponse:
def set_cookie(self, key, value, max_age=None, expires=None, domain=None, path='/', secure=False, httponly=False, samesite=None, secret=None, digestmod=hashlib.sha256):
"""
Set a response cookie.
Parameters:
- key: str, cookie name
- value: str, cookie value
- max_age: int, cookie lifetime in seconds
- expires: datetime or str, cookie expiration time
- domain: str, cookie domain
- path: str, cookie path (default: '/')
- secure: bool, require HTTPS
- httponly: bool, prevent JavaScript access
- samesite: str, SameSite attribute ('Strict', 'Lax', 'None')
- secret: str, secret for signed cookies
- digestmod: hashlib algorithm for signing
"""
def delete_cookie(self, key, **kwargs):
"""
Delete a cookie by setting it to expire.
Parameters:
- key: str, cookie name
- **kwargs: same domain/path options as set_cookie
"""Usage:
@route('/login', method='POST')
def login():
# Set regular cookie
response.set_cookie('user_id', '123', max_age=3600)
# Set secure, httponly cookie
response.set_cookie('session', 'abc123',
secure=True, httponly=True,
samesite='Strict')
# Set signed cookie
response.set_cookie('auth_token', 'token123',
secret='my-secret-key')
return 'Logged in'
@route('/logout')
def logout():
response.delete_cookie('user_id')
response.delete_cookie('session')
return 'Logged out'Handle response body content and encoding.
class BaseResponse:
@property
def body(self):
"""Response body content."""
@body.setter
def body(self, value):
"""Set response body content."""Raise HTTP responses as exceptions for flow control.
Base HTTP response exception that can be raised to return a response.
class HTTPResponse(Exception):
def __init__(self, body='', status=None, headers=None, **more_headers):
"""
Create HTTP response exception.
Parameters:
- body: str or bytes, response body
- status: int, HTTP status code
- headers: dict, response headers
- **more_headers: additional headers as keyword arguments
"""
@property
def status(self) -> int:
"""HTTP status code."""
@property
def status_line(self) -> str:
"""HTTP status line."""
@property
def body(self):
"""Response body."""
@property
def headers(self) -> HeaderDict:
"""Response headers."""
def set_header(self, name, value):
"""Set response header."""
def add_header(self, name, value):
"""Add response header."""HTTP error response exception.
class HTTPError(HTTPResponse):
def __init__(self, status=500, body=None, exception=None, traceback=None, **more_headers):
"""
Create HTTP error response.
Parameters:
- status: int, HTTP error status code
- body: str, error response body
- exception: Exception, original exception
- traceback: str, exception traceback
- **more_headers: additional headers
"""Utility functions for common HTTP responses.
def abort(code=500, text='Unknown Error.'):
"""
Raise HTTPError with specified status code.
Parameters:
- code: int, HTTP status code
- text: str, error message
Raises:
HTTPError: HTTP error response
"""
def redirect(url, code=None):
"""
Raise HTTPResponse that redirects to URL.
Parameters:
- url: str, redirect URL
- code: int, HTTP redirect status code (302 default)
Raises:
HTTPResponse: redirect response
"""Usage:
@route('/admin')
def admin():
if not user_is_admin():
abort(403, 'Access denied')
return 'Admin panel'
@route('/old-page')
def old_page():
redirect('/new-page', code=301) # Permanent redirect
@route('/login-required')
def protected():
if not logged_in():
redirect('/login')
return 'Protected content'Serve static files with proper headers and caching.
def static_file(filename, root, mimetype='auto', download=False, charset='UTF-8'):
"""
Serve static file with proper MIME type and caching headers.
Parameters:
- filename: str, file name to serve
- root: str, root directory path
- mimetype: str, MIME type ('auto' for detection)
- download: bool, force download with Content-Disposition
- charset: str, character encoding for text files
Returns:
HTTPResponse: file response with proper headers
Raises:
HTTPError: 404 if file not found, 403 if access denied
"""Usage:
@route('/static/<filepath:path>')
def serve_static(filepath):
return static_file(filepath, root='/var/www/static/')
@route('/download/<filename>')
def download_file(filename):
return static_file(filename, root='/var/downloads/',
download=True)
@route('/images/<filename>')
def serve_image(filename):
return static_file(filename, root='/var/images/',
mimetype='image/jpeg')Response objects integrate with WSGI for server compatibility.
class BaseResponse:
def __iter__(self):
"""Iterate over response body chunks."""
def close(self):
"""Clean up response resources."""
def __enter__(self):
"""Context manager entry."""
def __exit__(self, exc_type, exc_val, exc_tb):
"""Context manager exit."""Response objects can be bound to specific requests.
class LocalResponse(BaseResponse):
"""Thread-local response instance."""
def bind(self, environ):
"""Bind response to WSGI environ."""Install with Tessl CLI
npx tessl i tessl/pypi-bottle