创建强大Sanic插件的完整工具包
项目描述
欢迎使用Sanic插件工具包。
Sanic插件工具包(SPTK)是一个轻量级的Python库,旨在尽可能简化为Sanic异步HTTP服务器构建插件。
SPTK提供了一个可构建的Python基类对象 SanicPlugin,大多数Sanic插件将需要这些基本功能。
SPTK的Sanic插件实现方式类似于Sanic蓝本。您可以使用便利的装饰器以与蓝本相同的方式设置所有路由、中间件、异常处理程序和监听器,任何应用程序开发者都可以导入您的插件并将其注册到他们的应用程序中。
Sanic插件工具包不仅仅是蓝本样式的插件系统。它提供了一个增强的中间件系统,并管理上下文对象。
注意: 如果您需要与Sanic v21.03+兼容,请更新到SPTK v0.90.1。
增强的中间件系统
Sanic插件工具包中的中间件系统在原生Sanic中间件系统的基础上进行了扩展。它不仅包含两个中间件队列(“请求”和“响应”),SPF中的中间件系统还使用了五个额外的队列。
请求-前:这些中间件在应用自己的请求中间件之前运行。
请求-后:这些中间件在应用自己的请求中间件之后运行。
响应-前:这些中间件在应用自己的响应中间件之前运行。
响应-后:这些中间件在应用自己的响应中间件之后运行。
清理:这些中间件在所有上述中间件之后运行,在发送响应后运行,即使在响应为空的情况下也会运行。
因此,作为插件开发者,您可以决定您的中间件是在应用自己的中间件之前还是之后执行。
您还可以为您的插件中的每个中间件分配一个优先级,这样您可以更精确地控制中间件的执行顺序,尤其是在应用使用多个插件时。
上下文对象管理器
许多开发者认为Sanic缺少的一个特性是上下文对象。SPF提供了多个上下文对象,可用于不同的目的。
共享上下文:所有注册在SPF中的插件都可以访问一个共享的、持久的上下文对象,任何人都可以读取和写入。
请求上下文:所有插件都可以访问一个共享的临时上下文对象,任何人都可以读取和写入,该对象在请求开始时创建,在请求完成后删除。
插件上下文:所有插件都拥有自己的私有持久上下文对象,只有该插件可以读取和写入。
插件请求上下文:所有插件都获得一个在请求开始时创建并在请求完成后删除的临时私有上下文对象。
安装
使用pip或easy_install安装此扩展。
$ pip install -U sanic-plugin-toolkit
用法
使用Sanic插件工具包编写的简单插件看起来是这样的
# Source: my_plugin.py
from sanic_plugin_toolkit import SanicPlugin
from sanic.response import text
class MyPlugin(SanicPlugin):
def __init__(self, *args, **kwargs):
super(MyPlugin, self).__init__(*args, **kwargs)
# do pre-registration plugin init here.
# Note, context objects are not accessible here.
def on_registered(self, context, reg, *args, **kwargs):
# do post-registration plugin init here
# We have access to our context and the shared context now.
context.my_private_var = "Private variable"
shared = context.shared
shared.my_shared_var = "Shared variable"
my_plugin = MyPlugin()
# You don't need to add any parameters to @middleware, for default behaviour
# This is completely compatible with native Sanic middleware behaviour
@my_plugin.middleware
def my_middleware(request)
h = request.headers
#Do request middleware things here
#You can tune the middleware priority, and add a context param like this
#Priority must be between 0 and 9 (inclusive). 0 is highest priority, 9 the lowest.
#If you don't specify an 'attach_to' parameter, it is a 'request' middleware
@my_plugin.middleware(priority=6, with_context=True)
def my_middleware2(request, context):
context['test1'] = "test"
print("Hello world")
#Add attach_to='response' to make this a response middleware
@my_plugin.middleware(attach_to='response', with_context=True)
def my_middleware3(request, response, context):
# Do response middleware here
return response
#Add relative='pre' to make this a response middleware run _before_ the
#application's own response middleware
@my_plugin.middleware(attach_to='response', relative='pre', with_context=True)
def my_middleware4(request, response, context):
# Do response middleware here
return response
#Add attach_to='cleanup' to make this run even when the Response is None.
#This queue is fired _after_ response is already sent to the client.
@my_plugin.middleware(attach_to='cleanup', with_context=True)
def my_middleware5(request, context):
# Do per-request cleanup here.
return None
#Add your plugin routes here. You can even choose to have your context passed in to the route.
@my_plugin.route('/test_plugin', with_context=True)
def t1(request, context):
words = context['test1']
return text('from plugin! {}'.format(words))
应用开发者可以在其代码中使用您的插件,如下所示
# Source: app.py
from sanic import Sanic
from sanic_plugin_toolkit import SanicPluginRealm
from sanic.response import text
import my_plugin
app = Sanic(__name__)
realm = SanicPluginRealm(app)
assoc = realm.register_plugin(my_plugin)
# ... rest of user app here
支持使用配置文件定义当SPF添加到应用时加载的插件列表。
# Source: sptk.ini
[plugins]
MyPlugin
AnotherPlugin=ExampleArg,False,KWArg1=True,KWArg2=33.3
# Source: app.py
app = Sanic(__name__)
app.config['SPTK_LOAD_INI'] = True
app.config['SPTK_INI_FILE'] = 'sptk.ini'
realm = SanicPluginRealm(app)
# We can get the assoc object from SPF, it is already registered
assoc = spf.get_plugin_assoc('MyPlugin')
或者,如果开发者更喜欢使用旧方式(如Flask的方式),他们仍然可以这样操作
# Source: app.py
from sanic import Sanic
from sanic.response import text
from my_plugin import MyPlugin
app = Sanic(__name__)
# this magically returns your previously initialized instance
# from your plugin module, if it is named `my_plugin` or `instance`.
assoc = MyPlugin(app)
# ... rest of user app here
贡献
有问题、评论或改进意见?请在Github上创建问题
鸣谢
Ashley Sommer ashleysommer@gmail.com
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。