Sanic框架请求对象(Request)全面解析

Sanic框架请求对象(Request)全面解析

sanic Accelerate your web app development | Build fast. Run fast. sanic 项目地址: https://gitcode.com/gh_mirrors/sa/sanic

前言

在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查询参数有两种主要方式:

  1. request.args - 返回字典形式的参数
  2. 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请求。通过本文的介绍,你应该已经掌握了:

  1. 如何访问不同类型的请求体数据
  2. 使用请求上下文共享数据
  3. 自定义Request对象扩展功能
  4. 处理路径参数和查询参数
  5. 在非处理函数中获取当前请求

合理利用这些功能,可以构建出更加健壮、易维护的Web应用。Sanic的请求处理机制既保持了简单易用的特点,又提供了足够的灵活性满足各种复杂场景的需求。

sanic Accelerate your web app development | Build fast. Run fast. sanic 项目地址: https://gitcode.com/gh_mirrors/sa/sanic

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

符汝姿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值