1 """BaseHTTPServer that implements the Python WSGI protocol (PEP 333, rev 1.21) 2 3 This is both an example of how WSGI can be implemented, and a basis for running 4 simple web applications on a local machine, such as might be done when testing 5 or debugging an application. It has not been reviewed for security issues, 6 however, and we strongly recommend that you use a "real" web server for 7 production use. 8 9 For example usage, see the 'if __name__=="__main__"' block at the end of the 10 module. See also the BaseHTTPServer module docs for other API information. 11 """ 12 13 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 14 import urllib, sys 15 from wsgiref.handlers import SimpleHandler 16 17 __version__ = "0.1" 18 __all__ = ['WSGIServer', 'WSGIRequestHandler', 'demo_app', 'make_server'] 19 20 21 server_version = "WSGIServer/" + __version__ 22 sys_version = "Python/" + sys.version.split()[0] 23 software_version = server_version + ' ' + sys_version 24 25 26 class ServerHandler(SimpleHandler): 27 28 server_software = software_version 29 30 def close(self): 31 try: 32 self.request_handler.log_request( 33 self.status.split(' ',1)[0], self.bytes_sent 34 ) 35 finally: 36 SimpleHandler.close(self) 37 38 39 40 class WSGIServer(HTTPServer): 41 42 """BaseHTTPServer that implements the Python WSGI protocol""" 43 44 application = None 45 46 def server_bind(self): 47 """Override server_bind to store the server name.""" 48 HTTPServer.server_bind(self) 49 self.setup_environ() 50 51 def setup_environ(self): 52 # Set up base environment 53 env = self.base_environ = {} 54 env['SERVER_NAME'] = self.server_name 55 env['GATEWAY_INTERFACE'] = 'CGI/1.1' 56 env['SERVER_PORT'] = str(self.server_port) 57 env['REMOTE_HOST']='' 58 env['CONTENT_LENGTH']='' 59 env['SCRIPT_NAME'] = '' 60 61 def get_app(self): 62 return self.application 63 64 def set_app(self,application): 65 self.application = application 66 67 68 69 class WSGIRequestHandler(BaseHTTPRequestHandler): 70 71 server_version = "WSGIServer/" + __version__ 72 73 def get_environ(self): 74 env = self.server.base_environ.copy() 75 env['SERVER_PROTOCOL'] = self.request_version 76 env['REQUEST_METHOD'] = self.command 77 if '?' in self.path: 78 path,query = self.path.split('?',1) 79 else: 80 path,query = self.path,'' 81 82 env['PATH_INFO'] = urllib.unquote(path) 83 env['QUERY_STRING'] = query 84 85 host = self.address_string() 86 if host != self.client_address[0]: 87 env['REMOTE_HOST'] = host 88 env['REMOTE_ADDR'] = self.client_address[0] 89 90 if self.headers.typeheader is None: 91 env['CONTENT_TYPE'] = self.headers.type 92 else: 93 env['CONTENT_TYPE'] = self.headers.typeheader 94 95 length = self.headers.getheader('content-length') 96 if length: 97 env['CONTENT_LENGTH'] = length 98 99 for h in self.headers.headers: 100 k,v = h.split(':',1) 101 k=k.replace('-','_').upper(); v=v.strip() 102 if k in env: 103 continue # skip content length, type,etc. 104 if 'HTTP_'+k in env: 105 env['HTTP_'+k] += ','+v # comma-separate multiple headers 106 else: 107 env['HTTP_'+k] = v 108 return env 109 110 def get_stderr(self): 111 return sys.stderr 112 113 def handle(self): 114 """Handle a single HTTP request""" 115 116 self.raw_requestline = self.rfile.readline() 117 if not self.parse_request(): # An error code has been sent, just exit 118 return 119 120 handler = ServerHandler( 121 self.rfile, self.wfile, self.get_stderr(), self.get_environ() 122 ) 123 handler.request_handler = self # backpointer for logging 124 handler.run(self.server.get_app()) 125 126 127 128 def demo_app(environ,start_response): 129 from StringIO import StringIO 130 stdout = StringIO() 131 print >>stdout, "Hello world!" 132 print >>stdout 133 h = environ.items(); h.sort() 134 for k,v in h: 135 print >>stdout, k,'=', repr(v) 136 start_response("200 OK", [('Content-Type','text/plain')]) 137 return [stdout.getvalue()] 138 139 140 def make_server( 141 host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler 142 ): 143 """Create a new WSGI server listening on `host` and `port` for `app`""" 144 server = server_class((host, port), handler_class) 145 server.set_app(app) 146 return server 147 148 149 if __name__ == '__main__': 150 httpd = make_server('', 8000, demo_app) 151 sa = httpd.socket.getsockname() 152 print "Serving HTTP on", sa[0], "port", sa[1], "..." 153 import webbrowser 154 webbrowser.open('http://localhost:8000/xyz?abc') 155 httpd.handle_request() # serve one request, then exit 156