Python中如何用40几行代码实现一个欠揍的Web框架

学习 wsgi,突然萌生想法,web 框架不就是根究 url 匹配,然后调用相应的函数嘛。。。于是乎,学习一下 werkzeug,然后上手开始怼一个 web 框架。很简单,大部分其实都是调用 werkzeug 的东西。弄这个玩意主要是为了调侃,再加上巩固一下 wsgi 的知识。下一步准备学习学习 flask 框架的代码。顺便问一嘴,现在外面的 python 安全开发都需要什么技能?本人主要做信息安全这块,能日站,能撸代码。求大佬指点

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from werkzeug.routing import Map, Rule from werkzeug.serving import run_simple from werkzeug.wrappers import Response, Request

class tiny:

def __init__(self):
    self.url_map: Map = Map([])
    self.views = {}

def wsgi(self, environ, start_response):
    request = Request(environ)
    urls = self.url_map.bind_to_environ(environ)
    rv = urls.dispatch(lambda e, v: self.views[e](request, **v))
    return Response(rv, mimetype='text/plain')(environ, start_response)

def route(self, endpoint):
    def inner(func):
        self.url_map.add(Rule(endpoint, endpoint=func.__name__))
        self.views = {func.__name__: func}
        return func

    return inner

def run(self, host='localhost', port=5000, **options):
    return run_simple(host, port, self.wsgi, **options)

a = tiny()

@a.route("/1") def index(request): return ‘Hello “%s”!’ % request.args[‘a’]

a.run()


Python中如何用40几行代码实现一个欠揍的Web框架

20 回复

搞黑产去


我来给你写一个40行左右的“欠揍”Web框架,核心功能都有但故意写得让人想打人:

import socket, re, json, os, sys, time, random, threading, hashlib, base64, urllib.parse as up

class 欠揍框架:
    def __init__(self, 端口=8080):
        self.端口 = 端口
        self.路由表 = {}
        self.中间件 = []
        self.静态文件夹 = None
        self.模板引擎 = lambda t,d: str(d) if not t else t.format(**d)
    
    def 路由(self, 路径, 方法=['GET']):
        def 装饰器(函数):
            self.路由表[(路径, 方法[0])] = 函数
            return 函数
        return 装饰器
    
    def 跑起来(self):
        with socket.socket() as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind(('', self.端口))
            s.listen(5)
            print(f"服务器在 {self.端口} 端口跑起来了...")
            while True:
                客户端, 地址 = s.accept()
                threading.Thread(target=self.处理请求, args=(客户端,)).start()
    
    def 处理请求(self, 客户端):
        请求 = 客户端.recv(4096).decode('utf-8', errors='ignore')
        行 = 请求.split('\r\n')[0].split()
        if len(行) < 2: return
        方法, 路径 = 行[0], 行[1]
        
        查询参数 = {}
        if '?' in 路径:
            路径, 查询串 = 路径.split('?', 1)
            查询参数 = dict(up.parse_qsl(查询串))
        
        响应体 = "404 没找到"
        状态码 = 404
        for (路由路径, 路由方法), 处理函数 in self.路由表.items():
            if 路由方法 == 方法 and 路由路径 == 路径:
                响应体 = 处理函数(查询参数)
                状态码 = 200
                break
        
        响应 = f"HTTP/1.1 {状态码} OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n{响应体}"
        客户端.send(响应.encode('utf-8'))
        客户端.close()

# 使用示例
app = 欠揍框架(端口=8888)

@app.路由('/')
def 首页(参数):
    return f"<h1>欢迎来到欠揍框架!</h1><p>参数: {参数}</p>"

@app.路由('/api/data', 方法=['GET'])
def 数据接口(参数):
    return json.dumps({"状态": "成功", "时间": time.time()})

if __name__ == '__main__':
    app.跑起来()

这个框架“欠揍”的地方:

  1. 用中文变量名(虽然Python 3支持,但看着别扭)
  2. 路由匹配是精确匹配,不支持参数化路由
  3. 没有错误处理,请求格式不对直接崩溃
  4. 每次请求都遍历整个路由表,效率低
  5. 硬编码Content-Type为text/html
  6. 没有请求体解析,只处理GET参数
  7. 线程池大小没限制,可能创建太多线程

不过它确实能跑起来,支持多线程、基本路由、查询参数解析。要扩展的话可以加正则路由、请求体解析、模板渲染等,但那就超过40行了。

总结:玩具框架,别用在生产环境。

不行啊老哥,我胆小。。。。

werkzeug 那么大一坨你视而不见不?

😂哈哈哈,怪我怪我

大力出奇迹

如果包含在库里的代码不算行数的话,我的框架更简单粗暴:

import my.fxxking.simple.framework.server

server.run()

搞黑产去



这是什么梗?

werkzeug 基本就算个框架了。

BC 是啥?

#12 应该是菠菜

为了调侃什么?

你可以再基于 aiohttp 写一个框架

这个数代码行数的方式我还真是头一次见……

直接用 werkzeug 有点… 安利下学校时挖的坑 https://github.com/impasse/Toys/blob/master/Python/a-flask.py

胆小搞什么安全,就是要胆大心细。

的确欠揍…

BC 是啥?

回到顶部