• 仿写以WSGI为标准的web框架体


     1 动态web框架

      1.1 web框架要和web服务器软件分开(如MVC)

      1.2 web框架要和web服务器有良好的交互通信(python为自身的web框架制定了WSGI标准)

      1.3 web框架要和数据库有良好的读写通信方法

    2 关于WSGI标准

    WSGI将Web服务分成两个部分:服务器和应用程序。WGSI服务器只负责与网络相关的两件事:接收浏览器的 HTTP请求、向浏览器发送HTTP应答;而对HTTP请求的具体处理逻辑,则通过调用WSGI应用程序进行。

    2.1 一个个简单wsgi实现应用

    from wsgiref.simple_server import make_server
    
    
    def wsgi_app(environ, start_response):
        status = '200 ok'
        response_header = [('Content_Type', 'text/html')] 
        start_response(status, response_headers)
        return 'there is a wsgi app!'
    
    
    httpd = make_server('0.0.0.0',80,wsgi_app)    
    httpd.serve_forever()  

    environ是一个包含全部HTTP请求信息的字典/Dict,由WSGI服务器解包HTTP请求生成。

     2.2 WSGI模型特点:

      1.在web框架模块,以上面的栗子为例,web服务器软件会向web框架传递一个列表(environ)和一个函数(函数体在web服务器软件中实现)的引用(start_response),然后web框架要实现一个app函数,并将 "一个列表"和"一个函数的引用",作为两个参数;

      2.传递过来的列表内部存储了N个元组,这些元组包含了web服务器接收到的客户端浏览器的请求信息, 传递过来的函数参数的引用,可以用来返回请求资源的状态反馈(如果请求的资源可以访问,就会返回200,如果资源无法访问,就返回404或502之类的错误;

      3.传递过来的函数引用的调用比return更靠前,这样可以在返回正式的网页之前的这段时间,让web服务器软件做好接收数据的准备;(其实可以将函数的引用作为web框架与web服务器软件传递数据的的一种快捷方式);

    所以web服务器框架至少要实现三个功能

      1.创建 包含客户端请求头消息的列表(作为第一个参数传递);

      2.创建一个可以解析返回状态信息的函数(作为第二个参数传递);

      3.接收web框架内app函数返回的body,并将body与作为第二个参数的引用的函数的返回状态值组合,一同发送给客户端浏览器

     3 具体实现

    3.1 首先需要实现一个WISG的类作为server

    class WSGI(object):
        def __init__(self, port, app):
            里面主要是初始化的socket定义
            ....
            # 获取web框架的引用
            self.app = app  
            pass
        
        # 启动服务器对象入口函数
        def run_forever(self):
            self.create_new_socket()
            pass
            
        def create_new_socket(self):
            while True:
                ...
                # 对请求进行相应的处理
                self.deal_accept_data(new_client_socket)  
            
        def deal_accept_date(self, new_client_socket):
            # 接收数据
            recv_data = new_client_socket.recv(1024)
            # 将接收的数据转换为列表
            recv_data_list = recv_data.splitlines()
            
            获取请求头
            request_header = recv_data_list[0]
            
            # 该方法就是获取请求头中.../.../...html,用于app处理
            # GET /index.html HTTP/1.1
            html_name = get_html(request_header)
            
            # 进入动态app处理阶段
            # 获取web框架并且返回数据
            
            #创建一个字典,用于存储请求的参数
            enverion = dict()
            enverion['PATH_INFO'] = html_name
            
            # 启动web框架进行处理, 返回response的header和body
            dynamic_content = self.app(enverion, start_response)
            
            #发送和关闭
            new_client_socket.send(dynamic_content)
            new_client_socket.close()
            
        
        def main():
            # 导入web框架的app
            app = __import__(file_name)
            
            # 启动web服务器
            web_server = WSGI(port, app)
            web_server.run_forever()

    3.2 按照wsgi标准实现的web框架

    def app(enverion, start_response):
        # response是可以根据需求所改变的,可以根据environ的参数
        
        # 设置状态码
        status = '200 ok'
        # 设置返回的网页类型
        response_headers = [('Content_Type', 'text/html')]  
        
        # 向web框架中定义的函数start_response中传入头部信息
        # 先处理response的headers, 再对content进行返回
        start_response(status, response_headers)
        
        # 根据匹配的路径返回需要的response的body
        path_name = enverion['PATH_INFO]
        content = process_path(path_name)
        return content
        
        
    def process_path(path_name)
        寻找处理的函数
        v_func = match_path(path_name)
        content = v_func.return_result()
        return content

    from wsgiref.simple_server import make_server
    
    def application(environ, start_response):
        response_body = 'this is my first app'
        status = '200 OK'
        response_header = [('Content-Type', 'text/plain'),
                           ('Content-Length', str(len(response_body)))]
        start_response(status, response_header)
        return [response_body]
    
    
    httpd = make_server('localhost', 5000, application)
    
    httpd.handle_request()

     注意 application 返回结果是一个list包裹的的iterable对象

    根据wsgi教程上的注意事项,如果不是response_body不是在最后一行进行 list包裹,会造成只打印 len(iter) 个字符

    原因:In an older machine it is possible to notice it is slower. What happens is that the server iterated over the string sending a single byte at a time to the client. 此处引用 地址 http://wsgi.tutorial.codepoint.net/response-iterable

    解决办法:1 在最后进行 list包裹; 2 定义 content_length = sum([len(s) for s in response_body])

  • 相关阅读:
    ubuntu21.10(linux): 安装和使用ab(ApacheBench, Version 2.3)
    centos8(linux): nohup生成的日志切分
    EMR StarRocks 极速数据湖分析原理解析
    专访香侬科技:致力于让世界听到中文NLP的声音
    数智科技护航微出行
    无影云电脑支持企业快速实现居家办公
    深度解读「无影云电脑远程办公解决方案」
    系统性能分析从入门到进阶
    车脉科技:业内首创“车企体验式营销”
    基于Confluent+Flink的实时数据分析最佳实践
  • 原文地址:https://www.cnblogs.com/fuzzier/p/7623852.html
Copyright © 2020-2023  润新知