day5的课程真的有毒!!!
Topic sourcemiddleware
和RequestHandler
是一定要实现的,不然耦合度太高很容易混乱。
相反,add_route
可以省略,如果只加一个的话app.router.add_route
就足以应付了。
这是我重构过的版本, __import__
有一个黑魔法,不用写得这么复杂的:
mod = __import__(module_name, fromlist=[''])
加上了middleware
和 RequestHandler
后,走通了整个流程。
aiohttp的文档里说,middleware是一种自定义请求处理的强大机制。 貌似和JavaEE的过滤器,struts2的拦截器机制是差不多的意思。 都是责任链模式在项目中的实践。
async def logger_factory(app, handler): #这就是个装饰器呀
async def logger(request):
logging.info('Request: %s %s Begin>>>' % (request.method, request.path))
# await asyncio.sleep(0.3)
rst = (await handler(request))
return rst
return logger
async def response_factory(app, handler): #这个middleware比较不错,大家在handler里边可以返回各种类型的结果,在这里统一由廖大的response_factory给大家擦屁股。
。。。
middleware的代码示意:
m1( m2( m3( doFoo())))
middleware调用流程:
req -> m1 -> m2 -> m3 -> doFoo()- 一路return 原路返回
<- m1 <- m2 <- m2 <- resq - <-
知道了__call__
方法和__init__
的区别,RequestHandler
就是个普通类,没有什么特别的技巧。inspect
模块涨姿势了,把函数查了一遍户口本,这就是自省吧。
通过这几天的学习,粗粒度的掌握了框架的结构,闹懂了请求到来及响应的过程。以后学习的其他的web框架的难度会大大降低。
廖大屌爆了,在下服了。
@灰_手 把项目都做完了呀。
__import__ 指定fromList参数这里涨姿势了
你的add_routes()
很机智,廖大版的method 和 path 查到了不用实在是浪费。
RequestHandler
看起来写得和廖大的结构上不一样,粗略的搂了两眼,两份我都没仔细看具体实现。
在这里我得黑一下廖大,廖大版的RequestHandler
貌似把handler
函数的参数名写死了,handler的参数必须得叫request
。我感觉这样对用户不太友好,这是对用户赤裸裸地强J。
最好能用判断类型的方法来代替判断参数名的方法,来保证传入了一个request类型的参数。这样用户写handler的时候就r,req,request 什么的随意写了。用户用得爽了,框架才有市场。
@匿名sina网友V
我的已经是做完了,而且重构了不少地方,比如RequestHandler
,重构的理由在这里。
你黑的并不是地方,不是handler
函数的参数写死了,而是app.router.add_route
方法的第三个参数写死了,这里必需是一个只有一个参数request
的函数,所以才用__call__
统一封装成RequestHandler(handler)(request)
的形式,这样使得handler
的参数可以多样化。
然而RequestHandler
是整个项目中最值得黑的地方,你可以看看我和别人在楼下的评论就会知道真正值得黑的地方在哪里了XD
前边给RequestHandler
的评价过低了。
我说它是个普通类的前提是:
app.router.add_route('GET', '/', handler)
想要的handler只不过就是一个可以接收Request 类型实例,可以返回Response实例的一个callable而已,世界上可以满足这个需求的callable就像我的腿毛那么多,而RequestHandler
的实例恰好也满足这一条件。这就是个巧合,人为制造的巧合。
RequestHandler本身还有其他的支持它存在的意义。
A request handler can be any callable that accepts a Request instance as its only argument and returns a StreamResponse derived (e.g. Response) instance:
def handler(request):
return web.Response()
这个RequestHandler
,其实应该叫 RequestHandlerAdapter
才对。
它是个适配器,它把用户自定义参数的各种奇形怪状handler适配成了标准的 handler(request)调用。
add_routes最后直接用一个if更简洁
if isinstance(fn, types.FunctionType) and hasattr(fn, '__method__') and hasattr(fn, '__route__'):
add_route(app, fn)
看上去逻辑很多,但实际上是一种冗余
你没读过asyncio
的源码才会这样说,func = asyncio.coroutine(func)
这方法会内部处理func
是协程或生成器,根本无需在外先判断func
的类型,最终出来的就是标准的协程函数。
在add_routes
都用了method = getattr(func, '__method__', None)
了,还要在add_route
进行hasattr(fn, '__method__')
判断是没有意义的,在add_routes
中没有__method__
和__route__
属性时根本不会调用add_route
add_route
这些判断是为单独调用时存在的,然而并没有单独调用的场景。有单独调用的场景我倒不如直接用pp.router.add_route
了。
- 1
- 2
匿名sina网友V
屌炸天,太科幻了。跟着教程轻松愉快地攒出来一个web框架。 一看源码就停不下来,连续沉迷了两天,中了廖大的毒。 我现在没有用middleware和RequestHandler ,就用最朴素的方式来响应请求。 走通了一遍流程。简直不要太开心。
其中发现廖大代码里的一些小瑕疵 add_routes()
就这些了,后边我再把middleware和RequestHandler 部分补上。