处理请求

lessweb.Bridge类的对象支持add_route方法,可以指定一类请求应该由哪个「端点(endpoint)」来处理。所谓端点,是一个异步函数。用lessweb.(get|post|put|delete|patch|rest)_mapping()修饰这个异步函数,设置它绑定的方法和路径,它就成为了「端点(endpoint)」。

Endpoint的参数可以被框架“注入”,最简单的用法是用一个aiohttp.web.Request类型的变量,就能获取各种请求参数。端点可以返回aiohttp.web.Response对象,也可以直接返回dict|list类型的变量,框架会序列化为JSON返回。

示例如下:

from lessweb import Bridge, get_mapping, post_mapping, rest_mapping
from aiohttp.web import Request

@rest_mapping('GET', '/pet/{pet_id}')
async def get_pet_detail(request: Request):
    return {'pet_id': request.match_info['pet_id']}

@get_mapping('/pet')
async def get_pet_list(request: Request):  #注意必须用async,否则访问时会报错
    return {'name': request.query['name']}

@post_mapping('/pet')
async def create_pet(request: Request):
    pet = await request.json()
    return pet

if __name__ == '__main__':
    bridge = Bridge()
    bridge.add_route(get_pet_detail)
    bridge.add_route(get_pet_list)
    bridge.add_route(create_pet)
    bridge.run_app()

自动搜索端点

实际项目中endpoint可能非常多,要用add_route把每个endpoint调用一次是非常麻烦的。lessweb框架提供了根据包名(package name)自动搜索endpoint的能力。例如,我们先建立一个多文件的项目:

index.py
myapp/
myapp/endpoint/
myapp/endpoint/__init__.py
myapp/endpoint/get_pet_list.py
myapp/endpoint/create_pet.py

get_pet_detail.py文件内容为:

from lessweb import get_mapping
from aiohttp.web import Request


@get_mapping('/pet/{pet_id}')
async def get_pet_detail(request: Request):
    return {'pet_id': request.match_info['pet_id']}

create_pet.py文件内容为:

from lessweb import post_mapping
from aiohttp.web import Request


@post_mapping('/pet')
async def create_pet(request: Request):
    pet = await request.json()
    return pet

index.py文件内容为:

from lessweb import Bridge


if __name__ == '__main__':
    bridge = Bridge()
    bridge.add_route_scan('myapp.endpoint')
    bridge.run_app()

路径高级规则

lessweb的路径规则完全基于aiohttp的路径规则。

除了普通的固定路径,aiohttp支持有“可变资源”的路径。例如,一个路径为/a/{name}/c的资源将匹配所有路径为/a/b/c/a/1/c/a/etc/c的请求。变量部分是以{identifier}的形式指定的,其中identifier部分的匹配值可以在以后的请求处理程序中用Request.match_info获取。

默认情况下,每个{identifier}都以正则表达式[^{}/]+进行匹配。你也可以用{identifier:regex}的形式指定一个自定义的正则。例如,上面例子中的get_pet_detail()可做如下修改,以保证传入的pet_id一定是数字:

@get_mapping('/pet/{pet_id:[0-9]+}')
async get_pet_detail(request: Request):
    ...