美文网首页
Python入门教程: 一个基本的WSGI接口

Python入门教程: 一个基本的WSGI接口

作者: 破旧的大卡车 | 来源:发表于2017-12-20 14:37 被阅读75次

    主要参考: Let’s Build A Web Serve

    服务器

    #/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    '''
        A module for WSGI: As a demostration
        Usage:
            python wsgiserver.py wsgiapp:app
    '''
    
    __author__ = 'Van Abel'
    
    import socket
    import StringIO
    import sys
    
    
    class WSGIServer(object):
    
        socket_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM
        max_queue = 10
    
        def __init__(self, s_addr):
            # Create a listening socket
            self.s = s = socket.socket(
                self.socket_family,
                        self.socket_type
            )
            # Allow to reuse the same address
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            try:
                # Bind to addr, port
                s.bind(s_addr)
                # Listen on port
                s.listen(self.max_queue)
            except socket.error as e:
                print 'Server error >> %s ' % e
                sys.exit(1)
            # Get server host,port
            shost, self.s_port = self.s.getsockname()[:2]
            self.s_host = socket.getfqdn(shost)
            # Return headers set by web framework/app
            self.headers = []
    
        def set_app(self, app):
            self.app = app
    
        def server_forever(self):
            s = self.s
            while True:
                # New client conn
                self.c_conn, c_addr = s.accept()
                # Handle request and close
                #   Then loop over to wait for another client conn
                self.handle()
    
        def handle(self):
            # Read request from client
            self.r_data = r_data = self.c_conn.recv(1024)
            # Print formatted request data as 'curl -v'
            print(''.join(
                '< {line}\n'.format(line=line)
                    for line in r_data.splitlines()
            ))
            # Parse the request
            self.parse(r_data)
    
            # Construct environment dict useing r_data
            env = self.get_env()
    
            # Call app(defined in wsgiapp.py and pass in by set_app())
            #   and get result as HTTP response body
            b_data = self.app(env, self.start)
    
            # Construct a response and send to client
            self.send(b_data)
    
        def parse(self, data):
            headers = data.splitlines()[0].rstrip('\r\n')
            # Break down the headers
            (
                self.method,
                self.path,
                self.protcl
            ) = headers.split()
    
        def get_env(self):
            env = {}
    
            # Required WSGI variables
            env['wsgi.version'] = (1, 0)
            env['wsgi.url_scheme'] = 'http'
            env['wsgi.input'] = StringIO.StringIO(self.r_data)
            env['wsgi.errors'] = sys.stderr
            env['wsgi.multithread'] = False
            env['wsgi.multiprocess'] = False
            env['wsgi.run_once'] = False
    
            # Required CGI variables
            env['REQUEST_METHOD'] = self.method
            env['PATH_INFO'] = self.path
            env['SERVER_NAME'] = self.protcl
            env['SERVER_PORT'] = str(self.s_port)
    
            return env
    
        def start(self, status, r_headers, exc_info=None):
            # Add necessary server header
            s_headers = [
                ('Data', 'Tue, 19 Dec 2017 15:23:41 CST'),
                    ('Server', 'WSGI Server 0.1')
            ]
            self.headers = [status, r_headers + s_headers]
    
        def send(self, body):
            try:
                status, r_headers = self.headers
                r = 'HTTP/1.x {status}\r\n'.format(status=status)
                for header in r_headers:
                    r += '{0}: {1}\r\n'.format(*header)
                r += '\r\n'
                for data in body:
                    r += data
                # Print formatted response data as 'curl -v'
                print(''.join(
                    '> {line}\n'.format(line=line)
                    for line in r.splitlines()
                ))
                self.c_conn.sendall(r)
            finally:
                self.c_conn.close()
    
    SERVER_ADDRESS = (HOST, PORT) = '', 8000
    
    
    def make_server(s_addr, app):
        server = WSGIServer(s_addr)
        server.set_app(app)
        return server
    
    if __name__ == '__main__':
        if len(sys.argv) < 2:
            sys.exit('Usage:\n\tProvide a WSGI app object as module:callable')
    
        app_path = sys.argv[1]
        module, app = app_path.split(':')
        module = __import__(module)
        app = getattr(module, app)
        httpd = make_server(SERVER_ADDRESS, app)
        print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
        httpd.server_forever()
    

    客户端

    #/usr/bin/env python
    # -*- coding: utf-8 -*-
    '''
        wsgiapp.py
        A demo client for server_wsgi.py
    '''
    __author__ = 'Van Abel'
    
    def app(environ, start):
        # A barebones WSGI app
        # you can take it as a start point of your webframework
        status = '200 OK'
        resp_h = [('Content-Type', 'text/plain')]
        start(status, resp_h)
        return 'Hello world from a simple WSGI app!\n'
    

    相关文章

      网友评论

          本文标题:Python入门教程: 一个基本的WSGI接口

          本文链接:https://www.haomeiwen.com/subject/rbsgwxtx.html