zoukankan      html  css  js  c++  java
  • wsgi理解

    Web Server Gateway Interface 的缩写,即 Web 服务器网关接口。

    它规定了服务器怎么把请求信息告诉给应用,应用怎么把执行情况回传给服务器,这样的话,服务器与应用都按一个标准办事,只要实现了这个标准,服务器与应用随意搭配就可以,灵活度大大提高。

    首先,应用必须是一个可调用对象,可以是函数,也可以是实现了 __call__() 方法的对象。

    每收到一个请求,服务器会通过 application_callable(environ, start_response) 调用应用。

    应用在处理完毕准备返回数据的时候,先调用服务传给它的函数 start_response(status, headers, exec_info),最后再返回可迭代对象作为数据。(不理解可迭代对象的伙伴可以看下我之前的一篇文章《搞清楚Python的迭代器、可迭代对象、生成器》)

    其中,environ 必须是一个字典,包括了请求的相关信息,比如请求方式、请求路径等等,start_response 是应用处理完毕后,需要调用的函数,用于告诉服务设置响应的头部信息或错误处理等等。

    status 必须是 999 Message here 这样的字符串,比如 200 OK404 Not Found 等,headers 是一个由 (header_name, header_value) 这样的元祖组成的列表,最后一个 exec_info 是可选参数,一般在应用出现错误的时候会用到。


    def simple_app(environ, start_response):
        status = '200 OK'
        response_headers = [('Content-type', 'text/plain')]
        start_response(status, response_headers)
        return [f'Request {environ["REQUEST_METHOD"]}'
                f' {environ["PATH_INFO"]} has been'
                f' processed
    '.encode('utf-8')]
    
    这里定义了一个函数(可调用对象),它可以使用服务器传给它的请求相关的内容 environ,这里使用了 REQUEST_METHOD 和 PATH_INFO 信息。在返回之前调用了 start_response,方便服务器设置一些头部信息。
    然后是服务器
    
    import socket
    import sys
    
    
    class WSGIServer:
        def __init__(self):
            self.listener = socket.socket()
            self.listener.setsockopt(socket.SOL_SOCKET,
                                     socket.SO_REUSEADDR, 1)
            self.listener.bind(('0.0.0.0', 8080))
            self.listener.listen(1)
            print('Serving HTTP on 0.0.0.0'
                  ' port 8080 ...')
            self.app = None
            self.headers_set = None
    
        def set_app(self, application):
            self.app = application
    
        def start_response(self, status, headers):
            self.headers_set = [status, headers]
    
        def serve_forever(self):
            while True:
                listener = self.listener
                client_connection, client_address = 
                    listener.accept()
                print(f'Server received connection'
                      f' from {client_address}')
                request = client_connection.recv(1024)
                print(f'request we received: {request}')
    
                method, path, _ = request.split(b' ', 2)
                # 为简洁的说明问题,这里填充的内容有些随意
                # 如果有需要,可以自行完善
                environ = {
                    'wsgi.version': (1, 0),
                    'wsgi.url_scheme': 'http',
                    'wsgi.input': request,
                    'wsgi.errors': sys.stderr,
                    'wsgi.multithread': False,
                    'wsgi.multiprocess': False,
                    'wsgi.run_once': False,
                    'REQUEST_METHOD': method.decode('utf-8'),
                    'PATH_INFO': path.decode('utf-8'),
                    'SERVER_NAME': '127.0.0.1',
                    'SERVER_PORT': '8080',
                }
                app_result = self.app(environ, self.start_response)
    
                response_status, response_headers = self.headers_set
                response = f'HTTP/1.1 {response_status}
    '
                for header in response_headers:
                    response += f'{header[0]}: {header[1]}
    '
                response += '
    '
                response = response.encode('utf-8')
                for data in app_result:
                    response += data
    
                client_connection.sendall(response)
                client_connection.close()
    
    
    if __name__ == '__main__':
        if len(sys.argv) < 2:
            sys.exit('Argv Error')
        app_path = sys.argv[1]
        module, app = app_path.split(':')
        module = __import__(module)
        app = getattr(module, app)
    
        server = WSGIServer()
        server.set_app(app)
        server.serve_forever()

    首先定义了 start_response(status, headers) 函数,自身并不会调用。

    然后调用应用,将当前的请求信息 environ 和上面的 start_response 函数传给它,让其自己决定使用什么请求信息以及在处理完成准备返回数据之前调用 start_response 设置头部信息。



  • 相关阅读:
    基于 JavaEE 的在线考试系统
    别在发愁写页面了,强烈推荐几款傻瓜式扒网站神器!!!
    JAVA WEB 婚纱摄影管理系统(影楼系统)
    JAVA WEB 文件管理系统
    基于SSM的洗车管理系统
    基于JAVA WEB 的健身平台系统
    JAVA WEB 宠物商店
    JAVA WEB 家政信息发布平台
    JAVA WEB 文件管理系统
    JAVA WEB 选课系统
  • 原文地址:https://www.cnblogs.com/ighuahua/p/11174719.html
Copyright © 2011-2022 走看看