Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API 的插件框架 #413

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
27 changes: 24 additions & 3 deletions web/handlers/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,41 @@ class BodyArgument(ArgumentBase):
"""从 request.body 初始化,比如 POST JSON 情形
初始化函数原型为 init(bytes) -> self.type"""

init: Callable[[bytes], typing.Any] = None # type: ignore
init: Callable[[bytes | str], typing.Any] = None # type: ignore
"""参数初始化函数,初始化规则如下:
如果用户未提供且 self.type Callable,则使用 self.type;
如果用户未提供且 self.type 不是 Callable,则使用 lambda x: x。
该初始化函数原型为 init(bytes) -> self.type"""
该初始化函数原型为 init(bytes) -> self.type

request.body 默认是 bytes 类型,框架会尝试根据 Content-Type 进行解码,
但不保证一定能解码成功,所以建议手动判断一下参数类型。
"""

def __post_init__(self):
self.default = ""
self.default_display = ""

return super().__post_init__()

def try_decode(self, api: "ApiBase") -> str | bytes:
a76yyyy marked this conversation as resolved.
Show resolved Hide resolved
type = api.request.headers.get("Content-Type", "").lower()
if "charset=" not in type:
charset = "utf-8"
else:
start = type.index("charset=") + len("charset=")
try:
end = type.index(";", start)
except ValueError:
end = -1
charset = type[start:end]

try:
return api.request.body.decode(charset)
except UnicodeDecodeError:
return api.request.body

def get_value(self, api: "ApiBase"):
return self.init(api.request.body)
return self.init(self.try_decode(api))


class ApiMetaclass(type):
Expand Down
2 changes: 2 additions & 0 deletions web/handlers/api/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
# - 建议使用 `raise ApiError(status_code, reason)` 设置异常代码和原因
# - 允许 URL 传参(url?key=value)和 POST form 传参,不允许 /delay/value 形式传参(即不允许在 URL 中使用正则),
# - 参数尽量使用简单类型,参数的初始化函数尽量使用内置函数,使用 safe_eval 代替 eval,避免使用 safe_eval
# - 普通参数类型默认为 str,multi 参数类型默认为 list[str],
# Body 参数默认为 bytes|str,框架会尝试根据 Content-Type 进行解码,但不保证一定成功,所以建议在 init 中手动检查类型
# - 所有的 key 都使用 ASCII 字符,而不是中英文混用


Expand Down