Fast web framework for Python asyncio
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
This document covers BlackSheep's HTTP message handling system, including Request and Response classes, content types, headers, cookies, URL parsing, and data binding.
The Request class represents incoming HTTP requests with methods for accessing headers, body content, and parsed data.
from blacksheep import Request, URL
from typing import Optional, Dict, List
# Request creation and properties
request = Request("GET", b"https://example.com/users/123?q=search", headers=[
(b"Content-Type", b"application/json"),
(b"Authorization", b"Bearer token123")
])
# Basic properties
method: str = request.method # "GET", "POST", etc.
url: URL = request.url # Parsed URL object
query: Dict[str, List[str]] = request.query # Query parameters
route_values: Optional[Dict[str, str]] = request.route_values # Route params
cookies: Dict[str, str] = request.cookies # Request cookies
content: Optional[Content] = request.content # Request body content
# URL components
scheme: str = request.scheme # "http", "https"
host: str = request.host # "example.com"
path: str = request.path # "/users/123"
base_path: str = request.base_path # Application base path
# Client information
client_ip: str = request.client_ip # Client IP address
original_client_ip: str = request.original_client_ip # With setterfrom blacksheep.headers import Headers
# Header access methods
content_type: bytes = request.content_type()
etag: Optional[bytes] = request.etag
if_none_match: Optional[bytes] = request.if_none_match
# Generic header methods
first_header = request.get_first_header(b"Authorization")
all_auth_headers = request.get_headers(b"Authorization")
single_header = request.get_single_header(b"Content-Type")
has_auth = request.has_header(b"Authorization")
# Header manipulation
request.add_header(b"X-Custom", b"value")
request.set_header(b"Content-Type", b"application/json")
request.remove_header(b"X-Remove-Me")
# Content type checking
is_json = request.declares_json()
is_xml = request.declares_xml()
has_content_type = request.declares_content_type(b"application/json")
has_body = request.has_body()import json
from blacksheep.contents import FormPart
from typing import Any, Union
# Raw body access
body_bytes: Optional[bytes] = await request.read()
body_text: str = await request.text()
# Streaming body
async for chunk in request.stream():
process_chunk(chunk)
# Structured data parsing
json_data: Any = await request.json()
json_with_custom = await request.json(loads=custom_json_loads)
# Form data parsing
form_data: Union[Dict, None] = await request.form()
# Returns: {"field1": "value1", "field2": ["value2", "value3"]}
# Multipart form data
multipart_parts: List[FormPart] = await request.multipart()
for part in multipart_parts:
name = part.name.decode()
data = part.data
filename = part.file_name.decode() if part.file_name else None
content_type = part.content_type
# File uploads
uploaded_files: List[FormPart] = await request.files()
specific_files = await request.files("avatar") # Files with name "avatar"
for file_part in uploaded_files:
filename = file_part.file_name.decode()
content_type = file_part.content_type.decode()
file_data = file_part.data# Cookie access
cookie_value = request.get_cookie("session_id")
all_cookies = request.cookies # Dict[str, str]
# Session access (when sessions are configured)
from blacksheep.sessions import Session
session: Session = request.session
session["user_id"] = 123
user_id = session.get("user_id")
# Set cookies on request (for processing)
request.set_cookie("temp_cookie", "temp_value")# Authentication context
from guardpost import Identity
identity: Optional[Identity] = request.identity
if identity:
user_id = identity.id
claims = identity.claims
is_authenticated = identity.is_authenticated()
# ASGI scope access
scope = request.scope
asgi_version = scope.get("asgi", {}).get("version")BlackSheep provides utility functions for common request processing tasks.
from blacksheep.messages import (
is_cors_request, is_cors_preflight_request,
get_request_absolute_url, get_absolute_url_to_path
)
# CORS request detection
def is_cors_request(request: Request) -> bool:
"""Check if request is a CORS request"""
pass
def is_cors_preflight_request(request: Request) -> bool:
"""Check if request is a CORS preflight request"""
pass
# URL utilities
def get_request_absolute_url(request: Request) -> URL:
"""Get the absolute URL of the request"""
pass
def get_absolute_url_to_path(request: Request, path: str) -> URL:
"""Convert a path to absolute URL using request context"""
pass@app.middleware
async def cors_middleware(request: Request, handler):
if is_cors_preflight_request(request):
return Response(200, headers=[
(b"Access-Control-Allow-Origin", b"*"),
(b"Access-Control-Allow-Methods", b"GET, POST, PUT, DELETE"),
(b"Access-Control-Allow-Headers", b"Content-Type, Authorization")
])
if is_cors_request(request):
response = await handler(request)
response.headers.add(Header(b"Access-Control-Allow-Origin", b"*"))
return response
return await handler(request)
@app.get("/api/resource")
async def get_resource(request: Request):
# Get absolute URL for current request
current_url = get_request_absolute_url(request)
# Generate absolute URLs for related resources
related_url = get_absolute_url_to_path(request, "/api/related")
return json({
"current_url": current_url.value.decode(),
"related_url": related_url.value.decode()
})The Response class represents HTTP responses with status codes, headers, cookies, and content.
from blacksheep import Response, Content, TextContent, JSONContent
from blacksheep.headers import Headers
# Basic response creation
response = Response(200) # Status only
response = Response(200, content=TextContent("Hello World"))
# With headers
response = Response(
status=200,
headers=[(b"Content-Type", b"application/json")],
content=JSONContent({"message": "success"})
)
# Response properties
status: int = response.status # HTTP status code
reason: str = response.reason # Status reason phrase
content: Optional[Content] = response.content # Response body
cookies: Cookies = response.cookies # Response cookies# Header manipulation (inherits from Message)
response.add_header(b"X-API-Version", b"1.0")
response.set_header(b"Cache-Control", b"no-cache")
response.remove_header(b"X-Powered-By")
# Content type setting
response.set_header(b"Content-Type", b"application/json")
# Custom headers
response.headers.add(b"X-Response-Time", b"0.123")
response.headers.set(b"X-Request-ID", request_id.encode())from blacksheep.cookies import Cookie, CookieSameSiteMode
from datetime import datetime, timedelta
# Cookie creation
cookie = Cookie(
name="session_id",
value="abc123",
expires=datetime.utcnow() + timedelta(days=7),
domain="example.com",
path="/",
http_only=True,
secure=True,
max_age=604800, # 7 days in seconds
same_site=CookieSameSiteMode.LAX
)
# Set cookies on response
response.set_cookie(cookie)
response.set_cookies([cookie1, cookie2, cookie3])
# Remove cookies
response.unset_cookie("old_session")
response.remove_cookie("temp_cookie") # Alias for unset_cookie
# Get response cookies
all_cookies = response.get_cookies()
specific_cookie = response.get_cookie("session_id")# Response type checking
is_redirect: bool = response.is_redirect() # 3xx status codes
# Response modification
new_response = response.with_content(new_content)BlackSheep provides convenient helper functions for creating common HTTP responses.
from blacksheep.server.responses import (
ok, created, accepted, no_content,
bad_request, unauthorized, forbidden, not_found,
file, redirect, json, text, html,
ContentDispositionType
)
# Success responses
def ok(message: Any = None) -> Response:
"""Returns HTTP 200 OK response"""
pass
def created(message: Any = None, location: AnyStr = "") -> Response:
"""Returns HTTP 201 Created response with optional location header"""
pass
def accepted(message: Any = None) -> Response:
"""Returns HTTP 202 Accepted response"""
pass
def no_content() -> Response:
"""Returns HTTP 204 No Content response"""
pass
# Error responses
def bad_request(message: Any = None) -> Response:
"""Returns HTTP 400 Bad Request response"""
pass
def unauthorized(message: str = "Unauthorized") -> Response:
"""Returns HTTP 401 Unauthorized response"""
pass
def forbidden(message: str = "Forbidden") -> Response:
"""Returns HTTP 403 Forbidden response"""
pass
def not_found() -> Response:
"""Returns HTTP 404 Not Found response"""
pass
# File responses
def file(
value: FileInput,
content_type: str,
*,
file_name: str = None,
content_disposition: ContentDispositionType = ContentDispositionType.ATTACHMENT,
) -> Response:
"""Returns file response with content type and disposition"""
pass
# Content responses
def json(obj: Any) -> Response:
"""Returns JSON response"""
pass
def text(message: str) -> Response:
"""Returns plain text response"""
pass
def html(content: str) -> Response:
"""Returns HTML response"""
pass
def redirect(location: str, permanent: bool = False) -> Response:
"""Returns redirect response (302 or 301)"""
pass# File download with custom filename
@app.get("/download/{file_id}")
async def download_file(file_id: int):
file_data = await get_file_data(file_id)
return file(
file_data,
"application/pdf",
file_name="document.pdf",
content_disposition=ContentDispositionType.ATTACHMENT
)
# File display inline
@app.get("/preview/{image_id}")
async def preview_image(image_id: int):
image_data = await get_image_data(image_id)
return file(
image_data,
"image/jpeg",
content_disposition=ContentDispositionType.INLINE
)
# Created response with location
@app.post("/users")
async def create_user(user_data: FromJSON[dict]):
user = await create_user_in_db(user_data.value)
return created(
{"id": user.id, "name": user.name},
location=f"/users/{user.id}"
)BlackSheep provides various content types for request and response bodies.
from blacksheep.contents import Content
# Content properties and methods
class CustomContent(Content):
def __init__(self, data: str):
content_type = b"application/custom"
encoded_data = data.encode('utf-8')
super().__init__(content_type, encoded_data)
async def read(self) -> bytes:
return self.body
def dispose(self):
# Cleanup resources
pass
# Content properties
content_type: bytes = content.type
content_body: bytes = content.body
content_length: int = content.lengthfrom blacksheep.contents import TextContent
# Plain text content
text_content = TextContent("Hello, World!")
# Content-Type: text/plain; charset=utf-8
# Custom encoding (defaults to UTF-8)
text_content = TextContent("Hello", encoding="latin1")from blacksheep.contents import HTMLContent, HtmlContent
# HTML content (both aliases work)
html_content = HTMLContent("<h1>Hello</h1>")
html_content = HtmlContent("<p>Paragraph</p>")
# Content-Type: text/html; charset=utf-8
# Template rendering example
template = "<h1>Hello, {{name}}!</h1>"
rendered = template.replace("{{name}}", "Alice")
html_content = HTMLContent(rendered)from blacksheep.contents import JSONContent
import json
# JSON content with default serializer
data = {"users": [{"id": 1, "name": "Alice"}]}
json_content = JSONContent(data)
# Content-Type: application/json
# Custom JSON serializer
def custom_json_dumps(obj):
return json.dumps(obj, indent=2, sort_keys=True)
json_content = JSONContent(data, dumps=custom_json_dumps)
# Complex data serialization
from dataclasses import dataclass, asdict
@dataclass
class User:
id: int
name: str
user = User(1, "Alice")
json_content = JSONContent(asdict(user))from blacksheep.contents import FormContent
from typing import Dict, List, Tuple, Union
# URL-encoded form data
form_data: Dict[str, str] = {
"username": "alice",
"password": "secret",
"remember": "on"
}
form_content = FormContent(form_data)
# Content-Type: application/x-www-form-urlencoded
# Multiple values for same key
form_data: List[Tuple[str, str]] = [
("tags", "python"),
("tags", "web"),
("tags", "framework"),
("title", "My Post")
]
form_content = FormContent(form_data)
# Parsing form data
from blacksheep.contents import parse_www_form
form_string = "name=Alice&tags=python&tags=web"
parsed: Dict[str, Union[str, List[str]]] = parse_www_form(form_string)
# {"name": "Alice", "tags": ["python", "web"]}from blacksheep.contents import MultiPartFormData, FormPart
# Create form parts
text_part = FormPart(
name=b"title",
data=b"My Blog Post",
content_type=b"text/plain"
)
file_part = FormPart(
name=b"avatar",
data=image_bytes,
content_type=b"image/jpeg",
file_name=b"profile.jpg",
charset=b"utf-8"
)
# Multipart form
multipart = MultiPartFormData([text_part, file_part])
# Content-Type: multipart/form-data; boundary=...
# Access multipart properties
parts = multipart.parts
boundary = multipart.boundaryfrom blacksheep.contents import StreamedContent
from typing import AsyncIterable
# Streaming content for large responses
async def data_generator() -> AsyncIterable[bytes]:
for i in range(1000):
yield f"Data chunk {i}\n".encode()
streamed = StreamedContent(
content_type=b"text/plain",
data_provider=data_generator,
data_length=-1 # Unknown length
)
# Known length streaming
def file_streamer():
with open("large_file.txt", "rb") as f:
while chunk := f.read(8192):
yield chunk
file_size = os.path.getsize("large_file.txt")
streamed = StreamedContent(
content_type=b"application/octet-stream",
data_provider=file_streamer,
data_length=file_size
)from blacksheep.contents import ASGIContent
from typing import Callable, Dict, Any
# Content from ASGI receive callable
async def asgi_handler(scope: Dict[str, Any], receive: Callable, send: Callable):
# Create content from ASGI receive
content = ASGIContent(receive)
# Stream content
async for chunk in content.stream():
process_chunk(chunk)
# Or read all at once
body = await content.read()BlackSheep provides comprehensive header handling with case-insensitive access and manipulation.
from blacksheep.headers import Headers, Header
from typing import List, Tuple, Optional, Dict
# Header type
HeaderType = Tuple[bytes, bytes]
# Create headers collection
headers = Headers([
(b"Content-Type", b"application/json"),
(b"Authorization", b"Bearer token123"),
(b"Accept", b"application/json"),
(b"Accept", b"application/xml") # Multiple values
])
# Empty headers
headers = Headers()
# Header access methods
content_type_headers: Tuple[HeaderType] = headers.get(b"Content-Type")
header_tuples: List[HeaderType] = headers.get_tuples(b"Accept")
first_auth: Optional[bytes] = headers.get_first(b"Authorization")
single_ct: bytes = headers.get_single(b"Content-Type") # Throws if multiple
# Header manipulation
headers.add(b"X-Custom", b"value1")
headers.add(b"X-Custom", b"value2") # Multiple values allowed
headers.set(b"Content-Type", b"text/html") # Replace all existing
headers.remove(b"X-Remove-Me") # Remove all with this name
# Dictionary-like access
headers[b"Content-Type"] = b"application/json" # Set header
value = headers[b"Authorization"] # Get first value
del headers[b"X-Temp"] # Remove header
has_header = b"Content-Type" in headers # Check existence# Header iteration
for name, value in headers.items():
print(f"{name.decode()}: {value.decode()}")
# Header keys
header_names = headers.keys()
# Header merging
new_headers = [(b"X-New", b"value")]
headers.merge(new_headers)
# Dictionary update
header_dict = {b"Cache-Control": b"no-cache", b"X-Frame-Options": b"DENY"}
headers.update(header_dict)
# Add multiple headers
headers.add_many([
(b"X-Custom-1", b"value1"),
(b"X-Custom-2", b"value2")
])
# Or from dictionary
headers.add_many({
b"X-API-Version": b"1.0",
b"X-Rate-Limit": b"100"
})
# Header cloning
cloned_headers = headers.clone()
# Header combination
combined = headers + other_headers
headers += more_headersfrom blacksheep.headers import Header
# Create individual header
header = Header(b"Content-Type", b"application/json")
# Header properties
name: bytes = header.name # b"Content-Type"
value: bytes = header.value # b"application/json"
# Header iteration (name, then value)
for item in header:
print(item) # b"Content-Type", then b"application/json"
# Header equality
header1 = Header(b"Content-Type", b"application/json")
header2 = Header(b"content-type", b"application/json")
are_equal = header1 == header2 # Case-insensitive comparisonBlackSheep provides comprehensive cookie support with security features and expiration handling.
from blacksheep.cookies import Cookie, CookieSameSiteMode
from datetime import datetime, timedelta
# Basic cookie
cookie = Cookie("session_id", "abc123def456")
# Full cookie configuration
cookie = Cookie(
name="user_session",
value="encrypted_session_data",
expires=datetime.utcnow() + timedelta(days=30),
domain="example.com",
path="/",
http_only=True, # Prevent JavaScript access
secure=True, # Require HTTPS
max_age=2592000, # 30 days in seconds
same_site=CookieSameSiteMode.LAX
)
# Cookie properties
name: str = cookie.name
value: str = cookie.value
expires: Optional[datetime] = cookie.expires
domain: Optional[str] = cookie.domain
path: Optional[str] = cookie.path
http_only: bool = cookie.http_only
secure: bool = cookie.secure
max_age: int = cookie.max_age
same_site: CookieSameSiteMode = cookie.same_sitefrom blacksheep.cookies import CookieSameSiteMode
# SameSite attribute values
CookieSameSiteMode.UNDEFINED # Not specified
CookieSameSiteMode.LAX # Lax mode (default for most browsers)
CookieSameSiteMode.STRICT # Strict mode (no cross-site requests)
CookieSameSiteMode.NONE # None mode (requires Secure=True)
# Usage examples
session_cookie = Cookie("session", "value", same_site=CookieSameSiteMode.LAX)
csrf_cookie = Cookie("csrf", "token", same_site=CookieSameSiteMode.STRICT)
tracking_cookie = Cookie("track", "id", same_site=CookieSameSiteMode.NONE, secure=True)from blacksheep.cookies import (
datetime_to_cookie_format,
datetime_from_cookie_format,
parse_cookie,
write_response_cookie
)
# DateTime formatting for cookies
expire_time = datetime.utcnow() + timedelta(hours=24)
cookie_date: bytes = datetime_to_cookie_format(expire_time)
parsed_date: datetime = datetime_from_cookie_format(cookie_date)
# Cookie parsing from header value
cookie_header = b"session_id=abc123; Path=/; HttpOnly"
parsed_cookie: Cookie = parse_cookie(cookie_header)
# Cookie serialization for Set-Cookie header
cookie = Cookie("session", "value123", http_only=True)
set_cookie_header: bytes = write_response_cookie(cookie)
# b"session=value123; HttpOnly"
# Cookie cloning and comparison
cloned_cookie = cookie.clone()
is_equal = cookie == "session" # Compare by name
is_equal = cookie == cookie2 # Full comparisonBlackSheep provides comprehensive URL parsing, validation, and manipulation capabilities.
from blacksheep.url import URL, InvalidURL
# URL creation and parsing
try:
url = URL(b"https://api.example.com:8080/users/123?q=search&tag=python#section")
except InvalidURL as e:
print(f"Invalid URL: {e}")
# URL components
schema: Optional[bytes] = url.schema # b"https"
host: Optional[bytes] = url.host # b"api.example.com"
port: int = url.port # 8080
path: bytes = url.path # b"/users/123"
query: bytes = url.query # b"q=search&tag=python"
fragment: Optional[bytes] = url.fragment # b"section"
value: bytes = url.value # Original URL bytes
# URL properties
is_absolute: bool = url.is_absolute# URL modification
base_url = URL(b"https://api.example.com")
new_url = base_url.with_host(b"api2.example.com")
secure_url = base_url.with_scheme(b"https")
# URL joining
base = URL(b"https://api.example.com/v1")
relative = URL(b"users/123")
full_url = base.join(relative) # https://api.example.com/v1/users/123
# Get base URL (scheme + host + port)
base_only = url.base_url() # https://api.example.com:8080
# URL concatenation
url1 = URL(b"https://api.example.com")
url2 = url1 + b"/users" # URL + bytes
url3 = url1 + URL(b"/posts") # URL + URL# URL validation
def validate_url(url_string: str) -> bool:
try:
URL(url_string.encode())
return True
except InvalidURL:
return False
# Safe URL creation
def safe_url(url_string: str) -> Optional[URL]:
try:
return URL(url_string.encode())
except InvalidURL:
return NoneBlackSheep provides powerful data binding capabilities to extract and convert request data into typed parameters.
from blacksheep.server.bindings import (
FromJSON, FromQuery, FromRoute, FromForm,
FromHeader, FromCookie, FromServices, FromFiles,
FromBytes, FromText,
ClientInfo, ServerInfo, RequestUser, RequestURL, RequestMethod
)
# JSON body binding
@app.post("/users")
async def create_user(user_data: FromJSON[dict]):
user = user_data.value # Parsed JSON dict
return json({"created": True, "user": user})
# Type-safe JSON binding with dataclass
from dataclasses import dataclass
@dataclass
class CreateUserRequest:
name: str
email: str
age: int
@app.post("/users")
async def create_user_typed(request: FromJSON[CreateUserRequest]):
user = request.value # CreateUserRequest instance
return json({"name": user.name, "email": user.email})# Route parameter binding with type conversion
@app.get("/users/{user_id:int}")
async def get_user(user_id: FromRoute[int]):
user_id_value: int = user_id.value
return json({"user_id": user_id_value})
# Multiple route parameters
@app.get("/users/{user_id:int}/posts/{post_id:int}")
async def get_user_post(
user_id: FromRoute[int],
post_id: FromRoute[int]
):
return json({
"user_id": user_id.value,
"post_id": post_id.value
})
# String route parameters (default)
@app.get("/categories/{category_name}")
async def get_category(category_name: FromRoute[str]):
name: str = category_name.value
return json({"category": name})# Single query parameter
@app.get("/search")
async def search(q: FromQuery[str]):
query: str = q.value
return json({"query": query})
# Optional query parameters
@app.get("/users")
async def list_users(
page: FromQuery[int] = FromQuery(1),
limit: FromQuery[int] = FromQuery(10)
):
return json({
"page": page.value,
"limit": limit.value
})
# Multiple values for same parameter
@app.get("/posts")
async def filter_posts(tags: FromQuery[List[str]]):
tag_list: List[str] = tags.value # ["python", "web", "api"]
return json({"tags": tag_list})# Form data binding
@app.post("/contact")
async def contact_form(form_data: FromForm[dict]):
data: dict = form_data.value
name = data.get("name")
email = data.get("email")
return json({"received": True})
# Typed form binding
@dataclass
class ContactForm:
name: str
email: str
message: str
@app.post("/contact")
async def contact_typed(form: FromForm[ContactForm]):
contact: ContactForm = form.value
return json({
"name": contact.name,
"email": contact.email
})# Header binding
@app.get("/protected")
async def protected_endpoint(auth_header: FromHeader[str]):
# Header: Authorization: Bearer token123
token: str = auth_header.value # "Bearer token123"
return json({"authorized": True})
# Specific header name
@app.get("/api")
async def api_endpoint(api_key: FromHeader[str] = FromHeader(name="X-API-Key")):
key: str = api_key.value
return json({"api_key_received": True})
# Cookie binding
@app.get("/dashboard")
async def dashboard(session_id: FromCookie[str]):
session: str = session_id.value
return json({"session": session})
# Optional cookie with default
@app.get("/preferences")
async def preferences(
theme: FromCookie[str] = FromCookie("light", name="theme")
):
user_theme: str = theme.value
return json({"theme": user_theme})# File upload binding
@app.post("/upload")
async def upload_file(files: FromFiles):
uploaded_files = files.value # List[FormPart]
for file_part in uploaded_files:
filename = file_part.file_name.decode() if file_part.file_name else "unknown"
content_type = file_part.content_type.decode() if file_part.content_type else "unknown"
file_size = len(file_part.data)
# Save file
with open(f"uploads/{filename}", "wb") as f:
f.write(file_part.data)
return json({"uploaded": len(uploaded_files)})
# Specific file field
@app.post("/avatar")
async def upload_avatar(avatar: FromFiles = FromFiles(name="avatar")):
if avatar.value:
file_part = avatar.value[0] # First file
# Process avatar
return json({"avatar_uploaded": True})# Raw bytes binding
@app.post("/binary")
async def handle_binary(body: FromBytes):
raw_data: bytes = body.value
return Response(200, content=TextContent(f"Received {len(raw_data)} bytes"))
# Text binding
@app.post("/text")
async def handle_text(text: FromText):
content: str = text.value
return json({"text_length": len(content)})# Service injection
@app.get("/users/{user_id:int}")
async def get_user(
user_id: FromRoute[int],
user_service: FromServices[UserService]
):
service: UserService = user_service.value
user = await service.get_by_id(user_id.value)
return json(user)
# Multiple services
@app.post("/orders")
async def create_order(
order_data: FromJSON[dict],
order_service: FromServices[OrderService],
email_service: FromServices[EmailService]
):
order = await order_service.create(order_data.value)
await email_service.send_confirmation(order.email)
return json({"order_id": order.id})BlackSheep provides several binding classes to access request context information like client details, server info, and user identity.
from blacksheep.server.bindings import (
ClientInfo, ServerInfo, RequestUser, RequestURL, RequestMethod
)
from guardpost.authentication import Identity
from blacksheep import URL
# Context binding classes
class ClientInfo(BoundValue[Tuple[str, int]]):
"""Client IP and port information obtained from request scope"""
pass
class ServerInfo(BoundValue[Tuple[str, int]]):
"""Server IP and port information obtained from request scope"""
pass
class RequestUser(BoundValue[Identity]):
"""Returns the identity of the authenticated user"""
pass
class RequestURL(BoundValue[URL]):
"""Returns the URL of the request"""
pass
class RequestMethod(BoundValue[str]):
"""Returns the HTTP Method of the request"""
pass# Client connection information
@app.get("/info")
async def client_info(client: ClientInfo):
ip, port = client.value
return json({"client_ip": ip, "client_port": port})
# Server information
@app.get("/server-info")
async def server_info(server: ServerInfo):
host, port = server.value
return json({"server_host": host, "server_port": port})
# Authenticated user information
@app.get("/profile")
async def user_profile(user: RequestUser):
identity: Identity = user.value
return json({
"user_id": identity.claims.get("sub"),
"name": identity.claims.get("name"),
"roles": identity.claims.get("roles", [])
})
# Request URL information
@app.get("/request-info")
async def request_info(url: RequestURL, method: RequestMethod):
request_url: URL = url.value
http_method: str = method.value
return json({
"method": http_method,
"path": request_url.path,
"query": request_url.query,
"scheme": request_url.scheme,
"host": request_url.host
})This comprehensive request/response handling system provides type-safe, efficient processing of HTTP messages with rich content type support and flexible data binding capabilities.
Install with Tessl CLI
npx tessl i tessl/pypi-blacksheep