异步IO是如何来处理url的?
async def init(loop):
await orm.create_pool(loop=loop, host='127.0.0.1', port=3306, user='www', password='www', db='awesome')
app = web.Application(loop=loop, middlewares=[
logger_factory, response_factory
])
init_jinja2(app, filters=dict(datetime=datetime_filter))
add_routes(app, 'handlers')
add_static(app)
srv = await loop.create_server(app.make_handler(), '127.0.0.1', 9000)
logging.info('server started at http://127.0.0.1:9000...')
return srv
await orm.create_pool(loop=loop, host='127.0.0.1', port=3306, user='www', password='www', db='awesome')
app = web.Application(loop=loop, middlewares=[
logger_factory, response_factory
])
init_jinja2(app, filters=dict(datetime=datetime_filter))
add_routes(app, 'handlers')
add_static(app)
srv = await loop.create_server(app.make_handler(), '127.0.0.1', 9000)
logging.info('server started at http://127.0.0.1:9000...')
return srv
def add_routes(app, module_name):
n = module_name.rfind('.')
if n == (-1):
mod = __import__(module_name, globals(), locals())
else:
name = module_name[n+1:]
mod = getattr(__import__(module_name[:n], globals(), locals(), [name]), name)
for attr in dir(mod):
if attr.startswith('_'):
continue
fn = getattr(mod, attr)
if callable(fn):
method = getattr(fn, '__method__', None)
path = getattr(fn, '__route__', None)
if method and path:
add_route(app, fn)
为什么要获取url处理函数的函数对象?
add_routes不是用来注册url处理函数的吗?为什么到现在还没有注册?
from aiohttp import web
async def handle(request):
name = request.match_info.get('name', "Anonymous")
text = "Hello, " + name
return web.Response(text=text)
app = web.Application()
app.router.add_get('/', handle)
app.router.add_get('/{name}', handle)
web.run_app(app)
add_route(app, handles.index)
add_route(app, handles.blog)
add_route(app, handles.create_comment)
if callable(fn):
method = getattr(fn, '__method__', None)
path = getattr(fn, '__route__', None)
if method and path:
add_route(app, fn)
def add_route(app, fn):
method = getattr(fn, '__method__', None)
path = getattr(fn, '__route__', None)
if path is None or method is None:
raise ValueError('@get or @post not defined in %s.' % str(fn))
if not asyncio.iscoroutinefunction(fn) and not inspect.isgeneratorfunction(fn):
fn = asyncio.coroutine(fn)
logging.info('add route %s %s => %s(%s)' % (method, path, fn.__name__, ', '.join(inspect.signature(fn).parameters.keys())))
app.router.add_route(method, path, RequestHandler(app, fn))
method,path从何而来?
装饰器是如何起作用的?
def get(path):
'''
Define decorator @get('/path')
'''
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
return func(*args, **kw)
wrapper.__method__ = 'GET'
wrapper.__route__ = path
return wrapper
return decorator
@get('/')
async def index(request):
users = await User.findAll()
return {
'__template__': 'test.html',
'users': users
}
app.router.add_route(method, path, RequestHandler(app, fn))
为什么要通过RequestHandler类来创建url处理函数,前面不是已经有url处理函数了吗?为什么不直接拿来用?
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9
Cache-Control:max-age=0
Connection:keep-alive
Cookie:atsp=1513410396128_1513410396776; Hm_lvt_2efddd14a5f2b304677462d06fb4f964=1513308035,1513336392,1513396663,1513410397; Hm_lpvt_2efddd14a5f2b304677462d06fb4f964=1513410466
Host:www.liaoxuefeng.com
Referer:https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Connection:keep-alive
Content-Encoding:gzip
Content-Security-Policy:upgrade-insecure-requests
Content-Type:text/html; charset=utf-8
Date:Sat, 16 Dec 2017 07:49:37 GMT
Server:nginx/1.10.3 (Ubuntu)
Transfer-Encoding:chunked
X-Host:liaoxuefeng-2
X-Response-Time:24ms
async def __call__(self, request):
@get('/')
async def index(request):
users = await User.findAll()
return {
'__template__': 'test.html',
'users': users
}
经过装饰器的修饰后,index函数包含了请求方法GET/POST,请求路径path,以及HTTP请求头request,如何获取请求头呢?
request.cookie
_callable_中的参数是如何获取的?
def __init__(self, app, fn):
self._app = app
self._func = fn
self._has_request_arg = has_request_arg(fn)
self._has_var_kw_arg = has_var_kw_arg(fn)
self._has_named_kw_args = has_named_kw_args(fn)
self._named_kw_args = get_named_kw_args(fn)
self._required_kw_args = get_required_kw_args(fn)
这几个函数是用来干什么的?
怎么获取的?
http://127.0.0.1/api/comments
@get('/api/comments')
def api_comments(*, page='1'):
return ...
has_request_arg --> (*, page='1')
has_var_kw_arg --> OrderedDict([('page', "page='1'">)])
has_named_kw_args --> OrderedDict([('page', "page='1'">)])
get_named_kw_args --> OrderedDict([('page', "page='1'">)])
get_required_kw_args --> OrderedDict([('page', "page='1'">)])
if self._has_var_kw_arg or self._has_named_kw_args or self._required_kw_args:
if self._has_var_kw_arg or self._has_named_kw_args or self._required_kw_args:
if request.method == 'POST':
if not request.content_type:
return web.HTTPBadRequest('Missing Content-Type.')
ct = request.content_type.lower()
if ct.startswith('application/json'):
params = await request.json()
if not isinstance(params, dict):
return web.HTTPBadRequest('JSON body must be object.')
kw = params
elif ct.startswith('application/x-www-form-urlencoded') or ct.startswith('multipart/form-data'):
params = await request.post()
kw = dict(**params)
else:
return web.HTTPBadRequest('Unsupported Content-Type: %s' % request.content_type)
if request.method == 'GET':
qs = request.query_string
if qs:
kw = dict()
for k, v in parse.parse_qs(qs, True).items():
kw[k] = v[0]
http://www.face-python.wang/
if request.method == 'POST':
if not request.content_type:
return web.HTTPBadRequest('Missing Content-Type.')
ct = request.content_type.lower()
if ct.startswith('application/json'):
params = await request.json()
if not isinstance(params, dict):
return web.HTTPBadRequest('JSON body must be object.')
kw = params
elif ct.startswith('application/x-www-form-urlencoded') or ct.startswith('multipart/form-data'):
params = await request.post()
kw = dict(**params)
if request.method == 'GET':
qs = request.query_string
if qs:
kw = dict()
for k, v in parse.parse_qs(qs, True).items():
kw[k] = v[0]
INFO:root:add route POST /api/users => api_register_user(email, name, passwd)
has_request_arg --> (*, email, name, passwd)
has_var_kw_arg --> OrderedDict([('email', "email">), ('name', "name">), ('passwd', "passwd">)])
has_named_kw_args --> OrderedDict([('email', "email">), ('name', "name">), ('passwd', "passwd">)])
get_named_kw_args --> OrderedDict([('email', "email">), ('name', "name">), ('passwd', "passwd">)])
get_required_kw_args --> OrderedDict([('email', "email">), ('name', "name">), ('passwd', "passwd">)])
if not self._has_var_kw_arg and self._named_kw_args:
remove all unamed kw:
copy = dict()
for name in self._named_kw_args:
if name in kw:
copy[name] = kw[name]
kw = copy
for k, v in request.match_info.items():
if k in kw:
logging.warning('Duplicate arg name in named arg and kw args: %s' % k)
kw[k] = v
if self._has_request_arg:
kw['request'] = request
if self._required_kw_args:
for name in self._required_kw_args:
if not name in kw:
return web.HTTPBadRequest('Missing argument: %s' % name)
app.router.add_route(method, path, RequestHandler(app, fn))
参考文档:
[1]aiohttp
[2]urllib.parse
[3]the-meaning-of-the-module-name
[4]Python rfind()方法
[5]wireshare抓包教程
[6]Python import() 函数
勘误表:
错误1:
对于每个传进来的url,使用线程来处理url
线程是如何来处理url的?
更正:
对于每个传进来的url,使用异步IO来处理url
异步IO是如何来处理url的?
感谢评论区里的@小轲轲指明错误