Back to Blogs
sanic

Sanic Web Framework

Soloman
2022-01-28

Sanic Web Framework

1 请求

  • 以下变量可以作为request对象的属性访问
request.json
# JSON数据,一般用于获取POST的body数据

request.args
# {"name":["Soloman"],"age":[99]}
request.args.get('name')
# Soloman
request.args.getlist('name')
# ["Soloman"]

request.raw_args
# {"name":"Soloman","age":99}

request.form
# 表单数据 {"name":["Soloman"],"age":[99]}

request.body
# 原始数据 byte

request.headers
# 请求头信息 dict
request.socket
# (IP地址,端口) tuple

request.scheme
# 请求方式 http/https

request.url
# 完整的请求url
request.path
# 请求路径 /userinfo
request.query_string
# 请求字符串 name=Soloman&age=99
request.host
request.ip
request.port
request.file
request.token
# 授权标头的值

2 响应

  • 使用 sanic.response 中的函数来创建响应
from sanic.response import text, html, json, file,  redirect, raw, file_stream, stream
# 以下所有都支持请求头和状态值,分别传递给 headers 和 status 即可

return text('Hello, Soloman!')
return html('it is html!')
return json({"name":"Soloman"}, headers={"age": 99}, status=200)
return await file('/soloman/xxx.jpg')
return redirect('https://www.soloman.vip')

3 静态文件

from sanic import Sanic
app = Sanic()
app.static("/home","./static/home.html")

4 Cookies

  • Cookie可以像字典一样设置,并且具有如下参数:
    • expires:过期时间,Cookie在客户端浏览器上过期的时间
    • path:此Cookie使用的URL的子集。默认为/
    • comment:评论(元数据)
    • domain:Cookie的有效域
    • max-age:Cookie的活跃秒数
    • secure:指定Cookie是否仅通过HTTPS发送
    • httponly:指定Cookie是否不能被Javascript读取
# 设置 cookie
from sanic.response import text
@app.route("/set_cookie")
async def set_cookie(request):
  response = text("set cookie success")
  response.cookies["test"] = "test"
  response.cookies["test"]["max-age"] = 10
  return response

# 用户的Cookie可以通过Request对象的cookies字典进行访问
from sanic.response import text
@app.route("/get_info")
async def get_info(request):
  test = request.cookies.get("test")
  return text("cookie:{}".format(test)

5 中间件

  • 中间件是服务器在请求之前或之后执行的功能。Sanic提供两种类型的中间件:请求和响应。两者都是使用@app.middleware装饰器声明,两个装饰器分别需要传入一个代表其类型的参数:requestresponse
from sanic.response import text

# 将所有的请求的args添加一条name=Soloman,并且在响应头中添加name=Soloman
@app.route("/get_info")
async def get_info(request):
  print(request.url)
  return text("it is ok!")

@app.middleware("request")
async def get_request_middleware(request):
  print("请求中间件1")
  request.args.update({"name":"Soloman"})

@app.middleware("response")
async def get_response_middleware(request,response):
  print("响应中间件3")
  response.headers["name"] = "Soloman"

# 请求结果:从结果可以看出,request中间件是在接收到请求时立马触发的,而response中间件是在接收到响应时立马触发的。
请求中间件1
http://localhost:8000/get_info
响应中间件3

6 监听器

  • 如果需要在服务器启动/关闭的时候,执行一些特殊的代码,则可以使用以下监听器:

    • before_server_start:在服务器启动之前执行
    • after_server_start:在服务器启动之后执行
    • before_server_stop:在服务器关闭之前执行
    • after_server_stop:在服务器关闭之后执行
@app.listener("before_server_start")
async def before_server_start(request,loop):
  print("before_server_start")

@app.listener("after_server_start")
async def after_server_start(request,loop):
  print("after_server_start")

@app.listener("before_server_stop")
async def before_server_stop(request,loop):
  print("before_server_stop")

@app.listener("after_server_stop")
async def after_server_stop(request,loop):
  print("after_server_stop")

# 现在先启动服务,而后关闭,发现执行的顺序将会是这样:
before_server_start
after_server_start
before_server_stop
after_server_stop

7 基于类的视图

from sanic import Sanic
from sanic.views import HTTPMethodView
from sanic.response import text

class SanicView(HTTPMethodView):
  def get(self,request):
    return text("it is get")
  def post(self,request):
    return text("it is post")
  def put(self,request):
    return text("it is put")
  def patch(self,request):
    return text("it is patch")
  def delete(self,request):
    return text("it is delete")

app = Sanic()
app.add_route(SanicView.as_view(),"/method_view")
if __name__ == "__main__":
  app.run()

# 使用 async 定义
class SanicView(HTTPMethodView):
  async def get(self,request):
    return text("it is get")
app.add_route(SanicView.as_view(),"/method_view")

# 需要传递参数时,直接写入类方法中
class SanicView(HTTPMethodView):
  async def get(self,request,name):
    return text("it is get and name is {}".format(name))
app.add_route(SanicView.as_view(),"/<name>")