aiohttp 1.1的新内容

YARL 和 URL编码

自aiohttp 1.1起,aiohttp使用yarl来进行URL的处理。

新API

yarl.URL提供非常简便的方法来进行URL的相关操作。
客户端API仍然可以接受str的url形式,比如session.get()等价于session.get(yarl.URL('http://example.com'))
内部API均已选用yarl.URL做处理。aiohttp.CookieJar将只接收URL实例对象。
服务端方面添加了web.Request.urlweb.Request.rel_url来表示请求URL的相对和绝对路径。
使用URL是比较推荐的做法,现存的检索URL的方法已不赞成使用,并最终会被删除。
web异常引起的重定向也支持 yarl.URL作为地址。str也会一直支持使用的。
由路由得到URL也已做了修改。
主APIaiohttp.web.Request.url_for(name, **kwargs)现在会返回yarl.URL实例。已不支持查询参数,但也可以使用稍微繁琐的方式来添加查询参数:request.url_for('name_resource', param='a').with_query(arg='val')
返回的是相对URL,绝对URL需要使用request.url.join(request.url_for(...))来构建。

URL编码

在yarl.URL创建时会编码所有非ASCII的字符。
URL('https://www.python.org/путь')会被编码为'https://www.python.org/%D0%BF%D1%83%D1%82%D1%8C'
填写路由表时可以使用非ASCII编码的字符和百分号字符两种路径:

  1. app.router.add_get('/путь', handler)

  1. app.router.add_get('/%D0%BF%D1%83%D1%82%D1%8C', handler)

是同样的效果。因为在内部'/путь'会被编码成百分号形式。
路由匹配也同样接受两种URL格式: 原始形式和在经过路由模式转换的形式。

子应用

子应用被用来解决复杂的代码结构问题。假设我们有一个项目,项目中既有业务逻辑也有管理区域和调试工具。
管理区是一个独立地应用,有其自己的逻辑,而且所有的URL都带有如’/admin’前缀的。
所以我们可以创建一个完全独立的应用,并将其命名为’admin’,并把前缀附加到主app上:

  1. admin = web.Application()
  2. # setup admin routes, signals and middlewares
  3. app.add_subapp('/admin/', admin)

中间件和信号是链式的。
也就是说请求’/admin/something’app中的中间件会首先被调用,其次是admin。中间件是顺序调用得。
对于信号来说也一样——信号会被发送给app和admin。
常规信息如on_startup, on_shutdownon_cleanup会被发送到所有已注册过此信号的子应用。发出的参数是这个子应用的实例对象,并不是顶级应用的实例对象。
二层应用后可以嵌套第三层,并无层级限制。

Url 倒推

子应用中的Url倒推会给出带有特定前缀的url。
不过要得到URL,子应用的路由应该这么用:

  1. admin = web.Application()
  2. admin.add_get('/resource', handler, name='name')
  3. app.add_subapp('/admin/', admin)
  4. url = admin.router['name'].url_for()

得到的URL为'/admin/resource'

应用冻结

应用可以作为主app使用(app.make_handler())也可以做为子应用使用,但不要同时使用。
在使用.add_subapp()连接应用后,或开启顶级应用后,应用就被冻结了。
这也就意味着不管是注册新路由,新信号还是新中间件都是不允许的。改变冻结应用的状态(app[‘name’] = ‘value’)是不赞成使用的,并最终会删除。