文章目录
Sanic
Sanic Cookies读写
写web,Cookies会经常用到。Sanic可以读写Cookies,并以key-value(键值对)的方式存储。
读取cookies
from sanic.response import text
@app.route("/cookie")
async def test(request):
test_cookie = request.cookies.get('test')
return text("Test cookie set to: {}".format(test_cookie))
写入cookies
from sanic.response import text
@app.route("/cookie")
async def test(request):
response = text("There's a cookie up in this response")
response.cookies['test'] = 'It worked!'
response.cookies['test']['domain'] = '.test.com'
response.cookies['test']['httponly'] = True
return response
cookies属性
- expire(类型:datetime):cookie在客户端的浏览器到期时间。
- path(类型:string):cookie应用的URL子集。默认为/。
- comment(类型:string):注释(metadata)。
- domain(类型:string):指定cookie有效的域。 明确指定的域必须- 始终以点开头。
- max-age(类型:数字):cookie存活的秒数
- secure(类型:boolean):指定cookie是否只通过HTTPS发送。
- httponly(类型:boolean):指定cookie是否能被Javascript读取。
Sanic路由
url_for方法建立路由
1.传递给url_for的关键词参数如果不是请求参数就会被加入到URL的查询字符串
url = app.url_for('user_handler', user_id=3, arg_1='one', arg_2='two')
# /users/5?arg_1=one&arg_2=two
2.有些特殊参数(_anchor, _external, _scheme, _server)传递给url_for会建立特殊的url
url = app.url_for('user_handler', user_id=5, arg_one='one', _anchor='anchor')
# /users/5?arg_one=one#anchor
url = app.url_for('user_handler', user_id=5, arg_one='one', _external=True)
# //server/users/5?arg_one=one
# _external requires you to pass an argument _server or set SERVER_NAME in app.config if not url will be same as no _external
url = app.url_for('user_handler', user_id=5, arg_one='one', _scheme='http', _external=True)
# http://server/users/5?arg_one=one
# when specifying _scheme, _external must be True
# you can pass all special arguments at once
url = app.url_for('user_handler', user_id=5, arg_one=['one', 'two'], arg_two=2, _anchor='anchor', _scheme='http', _external=True, _server='another_server:8888')
# http://another_server:8888/users/5?arg_one=one&arg_one=two&arg_two=2#anchor
3.Websocket 路由
@app.websocket('/feed')
async def feed(request, ws):
while True:
data = 'hello!'
print('Sending: ' + data)
await ws.send(data)
data = await ws.recv()
print('Received: ' + data)
另外,app.add_websocket_route方法可以取代装饰器:
async def feed(request, ws):
pass
app.add_websocket_route(my_websocket_handler, '/feed')
4.strict_slashes参数
决定路由是否严格匹配末尾的斜杠;
Sanic静态文件
- 使用app.static()方法注册静态文件
# 提供文件夹`static`里面的文件到URL `/static`的访问。
app.static('/static', './static')
# 使用`url_for`创建URL时,默认为'static'的`name`可被省略。
app.url_for('static', filename='file.txt') == '/static/file.txt'
app.url_for('static', name='static', filename='file.txt') == '/static/file.txt'
- 对blueprint使用url_for创建的URL会加上/bp前缀。
bp = Blueprint('bp', url_prefix='/bp')
bp.static('/static', './static')
bp.static('/the_best.png', '/home/ubuntu/test.png', name='best_png')
- 方法app.static()支持虚拟主机。可以通过传入host参数实现
from sanic import Sanic
app = Sanic(__name__)
app.static('/static', './static')
app.static('/example_static', './example_static', host='www.test.com')
- 有时候需要Sanic提供大文件(比如,视频,图片等)的访问,可以选择使用流文件替代直接下载
from sanic import Sanic
app = Sanic(__name__)
app.static('/large_video.mp4', '/home/large_video.mp4', stream_large_files=True)
- 当stream_large_files为True时,Sanic将会使用file_stream()替代file()来提供静态文件访问。它默认的块大小是1KB,当然你可以根据需要修改块大小。
chunk_size = 1024 * 1024 * 8 # 设置块大小为 8KB
app.static('/large_video.mp4', '/home/ubuntu/large_video.mp4', stream_large_files=chunk_size)
Sanic中间件
中间件有两种类型:request和response,都是通过@app.middleware修饰器来声明的
- 请求中间件只接受request对象作为参数。
- 响应中间件同时接受request和response两个对象作为参数。
提前响应
这里的“提前”是指中间件直接返回HTTPResponse对象,这时请求将停止处理并返回response。如果这发生在request类型的中间件,路由处理函数将不会被调用。返回response将阻止后续的中间件继续执行
@app.middleware('request')
async def hand_request(request):
return text('the request1')
@app.middleware('response')
async def hand_response(request, response):
return text('the response2')
因为中间件hand_request返回了Response对象,其后续的中间件hand_response就不会被执行。
监听器
这些中间件通过修饰器@app.listener修饰接受app和loop参数的函数来实现。
- before_server_start
- after_server_start
- before_server_stop
- after_server_stop
监听器的注册
通过register_listener方法来注册监听器。
async def setup_db(app, loop):
app.db = await db_setup()
from my_listener import setup_db
app = Sanic()
app.register_listener(setup_db, 'before_server_start')
添加任务
后台任务在事件循环开始后执行
async def notify_server_started_after_five_seconds(app):
await asyncio.sleep(5)
print('Server successfully started!')
app.add_task(notify_server_started_after_five_seconds(app))