Sanic框架请求对象(Request)全面解析
前言
在Web开发中,处理HTTP请求是最基础也是最重要的环节之一。Sanic作为一款高性能的Python异步Web框架,提供了强大而灵活的请求处理机制。本文将深入解析Sanic中的Request对象,帮助开发者全面掌握请求处理的各项功能。
Request对象基础
在Sanic中,每个路由处理函数的第一个参数默认就是Request对象。这个对象包含了客户端发来的所有请求信息,开发者可以通过它获取请求头、请求体、查询参数等各种数据。
@app.get("/example")
async def example_handler(request):
return text("Hello World")
参数命名与类型注解
虽然约定俗成使用request
作为参数名,但实际上你可以使用任何合法的变量名。为了更好的代码提示和类型检查,建议使用类型注解:
from sanic.request import Request
@app.get("/typed")
async def typed_handler(request: Request):
return text("Done.")
请求体处理
Sanic提供了多种方式访问请求体内容,满足不同场景的需求。
JSON数据
当客户端发送JSON格式数据时,可以直接通过request.json
获取解析后的Python对象:
@app.post("/json")
async def handle_json(request):
data = request.json
return json({"received": data})
原始数据
如果需要原始字节数据,可以使用request.body
:
@app.post("/raw")
async def handle_raw(request):
raw_data = request.body
return text(f"Received {len(raw_data)} bytes")
表单数据
处理HTML表单提交时,request.form
提供了便捷的访问方式:
@app.post("/form")
async def handle_form(request):
username = request.form.get("username")
password = request.form.get("password")
return text(f"User: {username}")
注意表单数据是字典形式,但每个键对应的值是一个列表,因为HTTP允许同名参数多次出现。
文件上传
处理文件上传使用request.files
:
@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 = await get_current_user(request)
@app.get("/profile")
async def profile(request):
if not request.ctx.user:
return text("Please login first")
return text(f"Welcome {request.ctx.user.name}")
连接上下文
对于同一连接的多个请求,可以使用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.user_id = self.headers.get("X-User-ID")
app = Sanic("CustomApp", request_class=CustomRequest)
@app.get("/user")
async def get_user(request: CustomRequest):
return text(f"Your ID: {request.user_id}")
参数处理
路径参数
从URL路径中提取的参数会自动注入到处理函数中:
@app.get("/user/<user_id>")
async def get_user(request, user_id):
return text(f"User ID: {user_id}")
查询参数
获取URL查询参数有两种主要方式:
request.args
- 返回字典形式的参数request.query_args
- 返回原始的参数列表
@app.get("/search")
async def search(request):
query = request.args.get("q")
page = request.args.get("page", "1")
return text(f"Searching for '{query}' on page {page}")
获取当前请求
在某些场景下(如日志记录),可能需要获取当前请求对象:
from sanic import Request
def log_request_details():
try:
request = Request.get_current()
logger.info(f"Processing request {request.id}")
except Exception:
logger.info("No current request")
总结
Sanic的Request对象提供了丰富而强大的API来处理HTTP请求。通过本文的介绍,你应该已经掌握了:
- 如何访问不同类型的请求体数据
- 使用请求上下文共享数据
- 自定义Request对象扩展功能
- 处理路径参数和查询参数
- 在非处理函数中获取当前请求
合理利用这些功能,可以构建出更加健壮、易维护的Web应用。Sanic的请求处理机制既保持了简单易用的特点,又提供了足够的灵活性满足各种复杂场景的需求。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考