1"""BaseHTTPServer that implements the Python WSGI protocol (PEP 333, rev 1.21) 2 3This is both an example of how WSGI can be implemented, and a basis for running 4simple web applications on a local machine, such as might be done when testing 5or debugging an application. It has not been reviewed for security issues, 6however, and we strongly recommend that you use a "real" web server for 7production use. 8 9For example usage, see the 'if __name__=="__main__"' block at the end of the 10module. See also the BaseHTTPServer module docs for other API information. 11""" 12 13from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 14import urllib, sys 15from wsgiref.handlers import SimpleHandler 16 17__version__ = "0.1" 18__all__ = ['WSGIServer', 'WSGIRequestHandler', 'demo_app', 'make_server'] 19 20 21server_version = "WSGIServer/" + __version__ 22sys_version = "Python/" + sys.version.split()[0] 23software_version = server_version + ' ' + sys_version 24 25 26class 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 40class 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 69class 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(65537) 117 if len(self.raw_requestline) > 65536: 118 self.requestline = '' 119 self.request_version = '' 120 self.command = '' 121 self.send_error(414) 122 return 123 124 if not self.parse_request(): # An error code has been sent, just exit 125 return 126 127 handler = ServerHandler( 128 self.rfile, self.wfile, self.get_stderr(), self.get_environ() 129 ) 130 handler.request_handler = self # backpointer for logging 131 handler.run(self.server.get_app()) 132 133 134 135def demo_app(environ,start_response): 136 from StringIO import StringIO 137 stdout = StringIO() 138 print >>stdout, "Hello world!" 139 print >>stdout 140 h = environ.items(); h.sort() 141 for k,v in h: 142 print >>stdout, k,'=', repr(v) 143 start_response("200 OK", [('Content-Type','text/plain')]) 144 return [stdout.getvalue()] 145 146 147def make_server( 148 host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler 149): 150 """Create a new WSGI server listening on `host` and `port` for `app`""" 151 server = server_class((host, port), handler_class) 152 server.set_app(app) 153 return server 154 155 156if __name__ == '__main__': 157 httpd = make_server('', 8000, demo_app) 158 sa = httpd.socket.getsockname() 159 print "Serving HTTP on", sa[0], "port", sa[1], "..." 160 import webbrowser 161 webbrowser.open('http://localhost:8000/xyz?abc') 162 httpd.handle_request() # serve one request, then exit 163 httpd.server_close() 164