Sanic框架请求对象(Request)深度解析

Sanic框架请求对象(Request)深度解析

sanic 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请求。通过本文的介绍,你应该已经掌握了:

  1. 如何访问不同类型的请求体数据
  2. 利用上下文对象在请求生命周期中共享数据
  3. 通过自定义Request类扩展框架功能
  4. 处理路径参数和查询参数
  5. 使用高级特性如当前请求获取和类型化上下文

合理利用这些特性,可以构建出更加健壮、易维护的Sanic应用。

sanic sanic 项目地址: https://gitcode.com/gh_mirrors/san/sanic

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郁楠烈Hubert

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值