【Python】SnowAPI

import threading
from urllib.parse import urlparse, parse_qs


class Request:

    def __init__(self, content):
        self.content = content
        self.environ = self.content.decode()
        self.environ_lines = self.environ.split('\r\n')
        self.line = self.environ_lines[0]
        self.method, self.partial_url, self.protocol = self.line.split()

        url_parse_result = urlparse(self.partial_url)
        self.query = parse_qs(url_parse_result.query)
        self.path = url_parse_result.path

    @property
    def headers(self):
        return {k: v for k, v in map(lambda x: x.split(': '), self.environ_lines[1:-2])}

    @property
    def cookies(self):
        values = self.headers.get('Cookie') or self.headers.get('cookie')
        return {k: v for k, v in map(lambda x: x.split('=', 1), values.split('; '))}

    @property
    def body(self):
        return self.content.split(b'\r\n\r\n')[-1]

    def __str__(self):
        return '<Request [%s]>' % self.method


class Response:

    def __init__(self, content, status=200):
        self.version = 'http/1.1'
        self.content = content
        self.status = status

        self.line = '%s %s ok123' % (self.version, self.status)
        self.cookies = {}
        self.headers = {}
        self.body = self.content

    def prepare_line(self, line):
        return line + '\r\n'

    def prepare_headers(self, headers):
        content = ''
        for k, v in headers.items():
            content += f'{k}: {v}\r\n'

        return content + '\r\n'

    def prepare_body(self, body):
        return body

    def __str__(self):
        return '%s' \
               '%s' \
               '%s' % (self.prepare_line(self.line), self.prepare_headers(self.headers), self.prepare_body(self.body))


class SnowAPI:

    def __init__(self):
        self.routes = {}
        self.local = threading.local()
        self.exception_hooks = []
        self.before_request_hooks = []
        self.after_request_hooks = []

    def get(self, url):
        def wrapper(func):
            self.routes[f'GET {url}'] = func
            return func

        return wrapper

    def post(self, url):
        def wrapper(func):
            self.routes[f'POST {url}'] = func
            return func

        return wrapper

    def put(self, url):
        def wrapper(func):
            self.routes[f'PUT {url}'] = func
            return func

        return wrapper

    def delete(self, url):
        def wrapper(func):
            self.routes[f'DELETE {url}'] = func
            return func

        return wrapper

    def options(self, url):
        def wrapper(func):
            self.routes[f'OPTIONS {url}'] = func
            return func

        return wrapper

    def head(self, url):
        def wrapper(func):
            self.routes[f'HEAD {url}'] = func
            return func

        return wrapper

    def patch(self, url):
        def wrapper(func):
            self.routes[f'PATCH {url}'] = func
            return func

        return wrapper

    def trace(self, url):
        def wrapper(func):
            self.routes[f'TRACE {url}'] = func
            return func

        return wrapper

    def before_request(self, f):
        self.before_request_hooks.append(f)

    def after_request(self, f):
        self.after_request_hooks.append(f)

    def exception(self, f):
        self.exception_hooks.append(f)

    def process_request(self, request):
        # execute before request hook functions
        for func in self.before_request_hooks:
            func(request)

        try:
            # execute view functions
            response = self.routes['{} {}'.format(request.method, request.path)](request)
        except Exception as error:
            # execute exception hook functions
            for func in self.exception_hooks:
                func(request, error)

            response = """<h1>Not Found</h1>"""

        # execute after request hook functions
        for func in self.after_request_hooks:
            func(request)

        return str(response)

    def server(self, con):
        self.local.content = con.recv(1024)

        request = Request(self.local.content)
        response = self.process_request(request)
        con.send(response.encode())
        con.close()

    def run(self, host, port):
        import socket
        socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket.bind((host, port))
        socket.listen(128)
        print('[*] Starting server at http://{}:{}/'.format(host, port))

        while True:
            con, addr = socket.accept()
            threading.Thread(target=self.server, args=(con,)).start()


app = SnowAPI()


@app.exception
def exception(request, error):
    print(error)


@app.before_request
def _(request):
    print('请求之前')


@app.after_request
def _(request):
    print('请求之后')


@app.get('/index')
def index(request):
    print(request)
    return Response('<h1>hello world!</h1>')


@app.post('/index')
def index(request):
    print(request)
    return "{'code':0, 'msg':'ok'}"


if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8000)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值