simple_server.py 4.9 KB

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