Python无依赖轻量级Web框架xweb:低于500行代码如何实现?
我用极少的代码了实现一款 web 框架,目标是用低于 1000 行的代码实现 flask 的核心功能, xweb 框架基于 python3.5 以上开发,实在是居家旅行良品.
github 地址:https://github.com/gaojiuli/xweb
我的目标是用最少的代码实现符合现状的 web 框架,欢迎同样有兴趣的同学一起参与进来
说明
基于3.5开发
安装
pip install xweb
基本用法
from xweb.application import XWeb
app = XWeb()
@app.route(’/:name/’)
def call_my_name(name):
return ‘hi {}!’.format(name)
app.listen(3000)
请求与相应
from xweb.globals import request
request.path
request.query_string
request.query
request.files
request.forms
request.json
request.ip
request.hostname
request.headers
from xweb.globals import response
response.headers
response.status
response.body
中间件
from xweb.application import XWeb
app = XWeb()
@app.middleware(‘request’)
def print_on_request1():
print(“I print when a request is received by the server1”)
@app.middleware(‘request’)
def print_on_request2():
print(“I print when a request is received by the server2”)
@app.middleware(‘response’)
def print_on_response1():
print(“I print when a response is returned by the server1”)
@app.middleware(‘response’)
def print_on_response2():
print(“I print when a response is returned by the server2”)
@app.route(’/:name/’)
def call_my_name(name):
return ‘hi {}!’.format(name)
app.listen(3000)
我的目标是用最少的代码实现符合现状的 web 框架,欢迎同样有兴趣的同学一起参与进来
github 地址:https://github.com/gaojiuli/xweb
Python无依赖轻量级Web框架xweb:低于500行代码如何实现?
这个xweb框架的实现思路挺有意思的。核心就是基于Python标准库,用最少的代码实现基本的路由和请求处理。
下面是一个简化版的实现,大概100多行就能跑起来:
import socket
import re
from urllib.parse import parse_qs, urlparse
from http.server import BaseHTTPRequestHandler
from io import BytesIO
class Request:
def __init__(self, method, path, headers, body):
self.method = method
self.path = path
self.headers = headers
self.body = body
self.query = {}
if '?' in path:
self.path, query_string = path.split('?', 1)
self.query = parse_qs(query_string)
class Response:
def __init__(self, body='', status=200, content_type='text/html'):
self.body = body
self.status = status
self.content_type = content_type
class XWeb:
def __init__(self):
self.routes = {}
self.middlewares = []
def route(self, path, methods=['GET']):
def decorator(handler):
for method in methods:
self.routes[(method.upper(), path)] = handler
return handler
return decorator
def add_middleware(self, middleware):
self.middlewares.append(middleware)
def handle_request(self, request):
# 中间件处理
for middleware in self.middlewares:
request = middleware(request)
# 路由匹配
handler = self.routes.get((request.method, request.path))
if handler:
return handler(request)
return Response('Not Found', 404)
def run(self, host='127.0.0.1', port=8000):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((host, port))
server.listen(5)
print(f"Server running on http://{host}:{port}")
while True:
conn, addr = server.accept()
with conn:
data = conn.recv(1024)
if data:
# 解析HTTP请求
request_line, *headers_body = data.decode().split('\r\n', 1)
method, path, _ = request_line.split()
# 解析headers
headers_part, body_part = headers_body[0].split('\r\n\r\n', 1) if '\r\n\r\n' in headers_body[0] else (headers_body[0], '')
headers = {}
for line in headers_part.split('\r\n'):
if ': ' in line:
key, value = line.split(': ', 1)
headers[key] = value
request = Request(method, path, headers, body_part)
response = self.handle_request(request)
# 构建HTTP响应
response_headers = f"HTTP/1.1 {response.status} OK\r\n"
response_headers += f"Content-Type: {response.content_type}\r\n"
response_headers += f"Content-Length: {len(response.body)}\r\n"
response_headers += "\r\n"
conn.sendall(response_headers.encode() + response.body.encode())
# 使用示例
app = XWeb()
@app.route('/')
def home(request):
return Response('<h1>Hello XWeb!</h1>')
@app.route('/api/data', methods=['GET', 'POST'])
def api_data(request):
if request.method == 'GET':
return Response('{"status": "ok"}', content_type='application/json')
else:
return Response('{"status": "created"}', 201, 'application/json')
if __name__ == '__main__':
app.run()
关键实现点:
- 直接使用socket处理TCP连接,避免依赖
- 手动解析HTTP请求头,实现基本的路由匹配
- 用装饰器注册路由处理函数
- 支持中间件链式处理
要压缩到500行内,就得砍掉高级功能,只保留核心的路由和请求响应循环。真正的xweb可能还加了模板渲染、静态文件这些,但基本原理就这么简单。
总结:用标准库造轮子挺练手的。
那个。。。 method not allowed 不是 405 么😓
坐等日志、队列、 ORM(Postgresql&MySQL)。
讲真 Auth 就不要了
状态码从网上搞得,还没有专门整理
雪亮的眼!
这个是开发阶段选用的,只要符合 wsgi 就可以,实际部署的时候应选用 uwsgi 等工具
orm 我会重新启动一个项目,思路是分离出 django orm ,删减不常用的功能。我不打算把 orm 耦合进来,但是针对 xweb 定制一款符合现状的 orm 系统还是必要的。队列与日志同理,采用无耦合的形式开发。
想法不错
不过要说代码少的话,其实有个框架叫 bottle 的,记得代码很少,不知道还有人在用么
我的灵感来自 bottle , flask 和 sanic 三款框架,其中 bottle 和 flask 中为了 python2.7 添加太多代码,而 sanic 并非基于 wsgi ,有太多的依赖。这是我的初衷
可以啊, web.py 还是框架呢
哦。你这个也就是一个 action dispatcher ,一个框架重点在于 ORM
如你所说的话,Flask 和 Sanic 也不算框架咯?
很多框架都不自带 ORM ,怎么成重点了
orm 在我的计划之中,但是我不打算将它们耦合起来就像现在 Django ,我要的效果是 xweb 能快速地使用 peewee , sqlalchemy 等 orm ,也能用针对它开发的 orm 。同时这个 orm 应当能够和 flask , sanic 等结合使用。而不是强耦合地植入。
模板语言也不搞了吧。
json 部分弄好一点,实用性提高不少。
你的想法和我一样, xweb 简化满足用于接口开发即可
其实我只想要一个类似 php 那种一键部署的傻瓜工具
感谢你的建议, python 可以很容易实现傻瓜地部署,我会在项目完整后编写这样的脚本。
我在写的 web 框架也是这样搭建测试 HTTP 的,(基本所有 python web 框架都是使用 wsgiref 的 make_server 来本地测试的)
他这种写法并没有问题。 是要是对象里面有 call 函数 满足 wsgi 就可以了。
闲着没事的话可以给 bottle 增加 asyncIo 支持,就像 sanic 对 Flask 做的一样。
我可不乐意写那些兼容 python2 的代码
简单易懂,学习下,看看有没有机会做点贡献
建议去完善 sanic ,而不是再造一个轮子
sanic 使用 uvloop ,造成了无法使用像 flask 中的全局变量 request,response,g 等,并且它依赖于 aiofiles , httptools , ujson , uvloop 这几个库,如果这几个库更新,那么 sanic 不得不被牵着鼻子走. 我想实现的是无第三方依赖,并且摒弃 python2 .
bottle 本来就是兼容 Python2 和 3 的,但是 bottle 现在不支持 asyncio 。
我的意思是既然开发基于 python3, 那么所有为了 Python2 而生的代码都是多余的.


