zoukankan      html  css  js  c++  java
  • Notes on PEP333 (Python Web Server Gateway Interface)

    This note is about PEP3333- Python Web Server Gateway Interface. Refer to (Source: http://legacy.python.org/dev/peps/pep-3333/) for the complete description. 

    1. From the Application/Framwork side

    The application object is simply a callable object that accepts two arguments, named environ, and start_response, following the convention.

    Example:

    HELLO_WORLD = b"Hello world!
    "
    
    def simple_app(environ, start_response):
        """Simplest possible application object"""
        status = '200 OK'
        response_headers = [('Content-type', 'text/plain')]
        start_response(status, response_headers)
        return [HELLO_WORLD]

    2. From the Server/Gateway side

    The server or gateway invokes the application callable once for each request it receives from an HTTP client.

    Exmple:

    import os, sys
    
    enc, esc = sys.getfilesystemencoding(), 'surrogateescape'
    
    def unicode_to_wsgi(u):
        # Convert an environment variable to a WSGI "bytes-as-unicode" string
        return u.encode(enc, esc).decode('iso-8859-1')
    
    def wsgi_to_bytes(s):
        return s.encode('iso-8859-1')
    
    def run_with_cgi(application):
        environ = {k: unicode_to_wsgi(v) for k,v in os.environ.items()}
        environ['wsgi.input']        = sys.stdin.buffer
        environ['wsgi.errors']       = sys.stderr
        environ['wsgi.version']      = (1, 0)
        environ['wsgi.multithread']  = False
        environ['wsgi.multiprocess'] = True
        environ['wsgi.run_once']     = True
    
        if environ.get('HTTPS', 'off') in ('on', '1'):
            environ['wsgi.url_scheme'] = 'https'
        else:
            environ['wsgi.url_scheme'] = 'http'
    
        headers_set = []
        headers_sent = []
    
        def write(data):
            out = sys.stdout.buffer
    
            if not headers_set:
                 raise AssertionError("write() before start_response()")
    
            elif not headers_sent:
                 # Before the first output, send the stored headers
                 status, response_headers = headers_sent[:] = headers_set
                 out.write(wsgi_to_bytes('Status: %s
    ' % status))
                 for header in response_headers:
                     out.write(wsgi_to_bytes('%s: %s
    ' % header))
                 out.write(wsgi_to_bytes('
    '))
    
            out.write(data)
            out.flush()
    
        def start_response(status, response_headers, exc_info=None):
            if exc_info:
                try:
                    if headers_sent:
                        # Re-raise original exception if headers sent
                        raise exc_info[1].with_traceback(exc_info[2])
                finally:
                    exc_info = None     # avoid dangling circular ref
            elif headers_set:
                raise AssertionError("Headers already set!")
    
            headers_set[:] = [status, response_headers]
    
            # Note: error checking on the headers should happen here,
            # *after* the headers are set.  That way, if an error
            # occurs, start_response can only be re-called with
            # exc_info set.
    
            return write
    
        result = application(environ, start_response)
        try:
            for data in result:
                if data:    # don't send headers until body appears
                    write(data)
            if not headers_sent:
                write('')   # send headers now if body was empty
        finally:
            if hasattr(result, 'close'):
                result.close()

    3. Specification Details

    The application object must accept two positional arguments. For the sake of illustration, we have named them environ and start_response, but they are not required to have these names. A server or gateway must invoke the application object using positional(not keyword) arguments.

    The environ parameter is a dictonary object, containing CGI-style enviroment variables. This object must be a builtin Python dictionary (not a subclass, or other dictionary simulation), and the application is allowed to modify the dictionary in any way it desires. The dictionary must also include cetain WSGI-required variables, and may also include server-specific extension variables, named according to a covention.

    The start_reponse parameter is a callable accepting two required positional arguments, and one optional argument. For the sake of illustration, we have named these arguments statusresponse_headers, and exc_info, but they are not required to have these names, and the application must invoke the start_response callable using positional arguments.

    The status parameter is a status string of form '999 Message here', and response_headers is a list of (header_name, head_value) tuples describing the HTTP response header. The optional exc_info parameter is used only when the application has trapped an error and is attempting to display an error message to the browser.

    The start_response callable must return a write(body_data) callable that takes one postional parameter: a bytestring to be written as part of the HTTP response body.

    When called by the server, the application object must return an iterable yielding zero or more bytestrings. This can be accomplished in a variety of ways, such as by returning a list of bytestrings, or by the application being a generator function that yields bytestrings, or by the application being a class whose instances are iterable. Regardless of how it is accomplised, the application object must always return an iterable yielding zero or more bytestrings.

    The server or gateway must transmit the yielded bytestrings to the client in an unbuffered fashion, completing the transmission of each bytestring before requesting another one. (In other words, applications should perform their own buffering.)

    The application must invoke the start_response() callable before the iteralbe yields its first body bytestring, so that the server can send the headers before any body content. However, this invocatio nmay be performed by the iterable's first iteration, so servers must not assume that start_reponse() has been called before they begin iterating over the iterable.

    If the iterable returned by the appliation has close() method, the server or gateway must call that method upon completion of the current request, whether the request was completed normally, or terminated early due to an application error during iteration or an early disconnect of the browser. (The close() method requirement is to support resource release by the application.)

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 奇偶判断
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Qt: 访问容器(三种方法,加上for循环就四种了)good
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/3993176.html
Copyright © 2011-2022 走看看