定制请求#
定制上下文#
默认情况下,应用程序上下文是 SimpleNamespace
,允许你在其上设置任何你想要的属性。但是,你也可以选择传递任何其他对象。
app = Sanic(..., ctx=1)
app = Sanic(..., ctx={})
class MyContext:
...
app = Sanic(..., ctx=MyContext())
在大型代码库中拥有类型化的请求上下文对象非常便利。当然这不是必需的,但可能非常有用。
from sanic import Sanic, Request
from types import SimpleNamespace
class CustomRequest(Request):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ctx.user_id = self.headers.get("X-User-ID")
@staticmethod
def make_context() -> CustomContext:
return CustomContext()
@dataclass
class CustomContext:
user_id: str = None
定制请求上下文#
有时候,拥有你自己的 Request 类并告诉 Sanic 使用它而不是默认的类是有帮助的。
一个例子是如果你想修改默认的 request.id
生成器。
import time
from sanic import Request, Sanic, text
class NanoSecondRequest(Request):
@classmethod
def generate_id(*_):
return time.time_ns()
app = Sanic(..., request_class=NanoSecondRequest)
@app.get("/")
async def handler(request):
return text(str(request.id))
小技巧
重要的是要记住,你传递的是类而不是类的实例。
定制请求对象#
可以创建 sanic.request.Request
的子类来为请求对象添加额外的功能。这对于添加特定于你的应用程序的额外属性或方法非常有用。
例如,想象你的应用程序发送包含用户 ID 的自定义头。你可以创建自定义请求对象,它将解析该头并为你存储用户 ID。
from sanic import Sanic, Request
class CustomRequest(Request):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_id = self.headers.get("X-User-ID")
现在,在你的处理程序中,你可以访问 user_id
属性。
@app.route("/")
async def handler(request: CustomRequest):
return text(f"User ID: {request.user_id}")