| 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 |
|
|---|
| 41 |
|
|---|
| 42 | class WSGIServer(HTTPServer):
|
|---|
| 43 |
|
|---|
| 44 | """BaseHTTPServer that implements the Python WSGI protocol"""
|
|---|
| 45 |
|
|---|
| 46 | application = None
|
|---|
| 47 |
|
|---|
| 48 | def server_bind(self):
|
|---|
| 49 | """Override server_bind to store the server name."""
|
|---|
| 50 | HTTPServer.server_bind(self)
|
|---|
| 51 | self.setup_environ()
|
|---|
| 52 |
|
|---|
| 53 | def setup_environ(self):
|
|---|
| 54 | # Set up base environment
|
|---|
| 55 | env = self.base_environ = {}
|
|---|
| 56 | env['SERVER_NAME'] = self.server_name
|
|---|
| 57 | env['GATEWAY_INTERFACE'] = 'CGI/1.1'
|
|---|
| 58 | env['SERVER_PORT'] = str(self.server_port)
|
|---|
| 59 | env['REMOTE_HOST']=''
|
|---|
| 60 | env['CONTENT_LENGTH']=''
|
|---|
| 61 | env['SCRIPT_NAME'] = ''
|
|---|
| 62 |
|
|---|
| 63 | def get_app(self):
|
|---|
| 64 | return self.application
|
|---|
| 65 |
|
|---|
| 66 | def set_app(self,application):
|
|---|
| 67 | self.application = application
|
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 | class WSGIRequestHandler(BaseHTTPRequestHandler):
|
|---|
| 84 |
|
|---|
| 85 | server_version = "WSGIServer/" + __version__
|
|---|
| 86 |
|
|---|
| 87 | def get_environ(self):
|
|---|
| 88 | env = self.server.base_environ.copy()
|
|---|
| 89 | env['SERVER_PROTOCOL'] = self.request_version
|
|---|
| 90 | env['REQUEST_METHOD'] = self.command
|
|---|
| 91 | if '?' in self.path:
|
|---|
| 92 | path,query = self.path.split('?',1)
|
|---|
| 93 | else:
|
|---|
| 94 | path,query = self.path,''
|
|---|
| 95 |
|
|---|
| 96 | env['PATH_INFO'] = urllib.unquote(path)
|
|---|
| 97 | env['QUERY_STRING'] = query
|
|---|
| 98 |
|
|---|
| 99 | host = self.address_string()
|
|---|
| 100 | if host != self.client_address[0]:
|
|---|
| 101 | env['REMOTE_HOST'] = host
|
|---|
| 102 | env['REMOTE_ADDR'] = self.client_address[0]
|
|---|
| 103 |
|
|---|
| 104 | if self.headers.typeheader is None:
|
|---|
| 105 | env['CONTENT_TYPE'] = self.headers.type
|
|---|
| 106 | else:
|
|---|
| 107 | env['CONTENT_TYPE'] = self.headers.typeheader
|
|---|
| 108 |
|
|---|
| 109 | length = self.headers.getheader('content-length')
|
|---|
| 110 | if length:
|
|---|
| 111 | env['CONTENT_LENGTH'] = length
|
|---|
| 112 |
|
|---|
| 113 | for h in self.headers.headers:
|
|---|
| 114 | k,v = h.split(':',1)
|
|---|
| 115 | k=k.replace('-','_').upper(); v=v.strip()
|
|---|
| 116 | if k in env:
|
|---|
| 117 | continue # skip content length, type,etc.
|
|---|
| 118 | if 'HTTP_'+k in env:
|
|---|
| 119 | env['HTTP_'+k] += ','+v # comma-separate multiple headers
|
|---|
|
|---|