Sanic框架请求对象(Request)深度解析
sanic 项目地址: https://gitcode.com/gh_mirrors/san/sanic
作为Python异步Web框架Sanic的核心组件之一,Request对象承载了HTTP请求的所有关键信息。本文将全面剖析Sanic的Request对象,帮助开发者更好地理解和使用这一重要组件。
Request对象基础
在Sanic的路由处理函数中,第一个参数通常就是Request对象实例。这个对象包含了客户端请求的所有信息,从请求头到请求体,从查询参数到路径参数,应有尽有。
@app.get("/example")
async def handler(request):
return text("Hello World")
虽然按照惯例我们将这个参数命名为request
,但实际上你可以使用任何合法的变量名:
@app.get("/example")
async def handler(req):
return text("Hello World")
类型注解
为了获得更好的IDE支持和代码提示,建议为Request对象添加类型注解:
from sanic.request import Request
@app.get("/typed")
async def typed_handler(request: Request):
return text("Done.")
请求体处理
Sanic提供了多种方式来访问请求体内容,满足不同场景的需求。
JSON数据
@app.post("/json")
async def handle_json(request):
data = request.json # 自动解析JSON数据
return json({"received": data})
原始数据
@app.post("/raw")
async def handle_raw(request):
raw_data = request.body # 获取原始字节数据
return text(f"Received {len(raw_data)} bytes")
表单数据
处理表单数据时需要注意,HTTP协议允许同一个键对应多个值:
@app.post("/form")
async def handle_form(request):
username = request.form.get("username") # 获取第一个值
all_values = request.form.getlist("interests") # 获取所有值
return text(f"Hello {username}, your interests: {', '.join(all_values)}")
文件上传
文件上传处理同样支持多文件上传场景:
@app.post("/upload")
async def handle_upload(request):
uploaded_file = request.files.get("file")
if uploaded_file:
file_content = uploaded_file.body
return text(f"Received file with {len(file_content)} bytes")
return text("No file uploaded")
请求上下文
request.ctx
request.ctx
是请求级别的上下文对象,非常适合存储请求相关的临时数据:
@app.middleware("request")
async def authenticate(request):
# 模拟认证过程
request.ctx.user = {"id": 123, "name": "John Doe"}
@app.get("/profile")
async def profile(request):
if not hasattr(request.ctx, "user"):
return text("Unauthorized", status=401)
return json(request.ctx.user)
连接上下文
对于保持连接的多个请求,可以使用request.conn_info.ctx
共享状态:
@app.on_request
async def count_requests(request):
if not hasattr(request.conn_info.ctx, "count"):
request.conn_info.ctx.count = 0
request.conn_info.ctx.count += 1
@app.get("/counter")
async def show_counter(request):
return text(f"Request count: {request.conn_info.ctx.count}")
自定义Request类
Sanic允许开发者自定义Request类,扩展框架功能:
from sanic import Request, Sanic
class CustomRequest(Request):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.client_ip = self.headers.get("X-Forwarded-For", self.ip)
app = Sanic("CustomApp", request_class=CustomRequest)
@app.get("/ip")
async def show_ip(request: CustomRequest):
return text(f"Your IP: {request.client_ip}")
参数处理
路径参数
路径参数会自动注入到处理函数中:
@app.get("/user/<user_id>")
async def get_user(request, user_id):
return text(f"Fetching user {user_id}")
查询参数
查询参数可以通过request.args
访问:
@app.get("/search")
async def search(request):
query = request.args.get("q", "")
page = int(request.args.get("page", "1"))
return text(f"Searching for '{query}' on page {page}")
对于多值参数:
@app.get("/filters")
async def apply_filters(request):
colors = request.args.getlist("color") # 获取所有color参数值
return json({"applied_filters": colors})
高级特性
获取当前请求
在非处理函数中获取当前请求:
from sanic import Request
def log_request_details():
try:
request = Request.get_current()
print(f"Processing request {request.id}")
except Exception:
print("No current request")
自定义上下文类型
为获得更好的类型提示,可以自定义上下文类型:
from dataclasses import dataclass
from sanic import Request
@dataclass
class CustomContext:
user_id: str = None
is_admin: bool = False
class TypedRequest(Request):
@staticmethod
def make_context() -> CustomContext:
return CustomContext()
总结
Sanic的Request对象提供了丰富而强大的API来处理HTTP请求。通过本文的介绍,你应该已经掌握了:
- 如何访问不同类型的请求体数据
- 利用上下文对象在请求生命周期中共享数据
- 通过自定义Request类扩展框架功能
- 处理路径参数和查询参数
- 使用高级特性如当前请求获取和类型化上下文
合理利用这些特性,可以构建出更加健壮、易维护的Sanic应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考