为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点:
接下来的笔墨将着重于最后一点。这篇文章旨在通过对设计和实现过程一步一步的阐述告诉读者,我在完成一个小型的服务器和框架之后学到了什么。你可以在这个代码仓库中找到这个项目的完整代码。
我希望这篇文章可以鼓励更多的人来尝试,因为这确实很有趣。它让我知道了 web 应用是如何工作的,而且这比我想的要容易的多!
范围
框架可以处理请求-响应周期、身份认证、数据库访问、模板生成等部分工作。Web 开发者使用框架是因为,大多数的 web 应用拥有大量相同的功能,而对每个项目都重新实现同样的功能意义不大。
- 处理 HTTP 的 GET 和 POST 请求。你可以在这篇 wiki 中对 HTTP 有个大致的了解。
- 实现异步操作(我喜欢 Python 3 的 asyncio 模块)。
- 简单的路由逻辑以及参数撷取。
- 像其他微型框架一样,提供一个简单的用户级 API 。
- 支持身份认证,因为学会这个很酷啊(微笑)。
- 将只支持 HTTP 1.1 的一个小子集,不支持传输编码transfer-encoding、HTTP 认证http-auth、内容编码content-encoding(如 gzip)以及持久化连接等功能。
- 不支持对响应内容的 MIME 判断 - 用户需要手动指定。
- 不支持 WSGI - 仅能处理简单的 TCP 连接。
- 不支持数据库。
我觉得一个小的用例可以让上述内容更加具体,也可以用来演示这个框架的 API:
-
from diy_framework import App, Router
-
from diy_framework.http_utils import Response
-
-
-
# GET simple route
-
async def home(r):
-
rsp = Response()
-
rsp.set_header('Content-Type', 'text/html')
-
rsp.body = '<html><body><b>test</b></body></html>'
-
return rsp
-
-
-
# GET route + params
-
async def welcome(r, name):
-
return "Welcome {}".format(name)
-
-
# POST route + body param
-
async def parse_form(r):
-
if r.method == 'GET':
-
return 'form'
-
else:
-
name = r.body.get('name', '')[0]
-
password = r.body.get('password', '')[0]
-
-
return "{0}:{1}".format(name, password)
-
-
# application = router + http server
-
router = Router()
-
router.add_routes({
-
r'/welcome/{name}': welcome,
-
r'/': home,
-
r'/login': parse_form,})
-
-
app = App(router)
-
app.start_server()
' 用户需要定义一些能够返回字符串或 Response
对象的异步函数,然后将这些函数与表示路由的字符串配对,最后通过一个函数调用(start_server
)开始处理请求。