(root)/
Python-3.12.0/
Lib/
wsgiref/
simple_server.py
       1  """BaseHTTPServer that implements the Python WSGI protocol (PEP 3333)
       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 http.server import BaseHTTPRequestHandler, HTTPServer
      14  import sys
      15  import urllib.parse
      16  from wsgiref.handlers import SimpleHandler
      17  from platform import python_implementation
      18  
      19  __version__ = "0.2"
      20  __all__ = ['WSGIServer', 'WSGIRequestHandler', 'demo_app', 'make_server']
      21  
      22  
      23  server_version = "WSGIServer/" + __version__
      24  sys_version = python_implementation() + "/" + sys.version.split()[0]
      25  software_version = server_version + ' ' + sys_version
      26  
      27  
      28  class ESC[4;38;5;81mServerHandler(ESC[4;38;5;149mSimpleHandler):
      29  
      30      server_software = software_version
      31  
      32      def close(self):
      33          try:
      34              self.request_handler.log_request(
      35                  self.status.split(' ',1)[0], self.bytes_sent
      36              )
      37          finally:
      38              SimpleHandler.close(self)
      39  
      40  
      41  
      42  class ESC[4;38;5;81mWSGIServer(ESC[4;38;5;149mHTTPServer):
      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  class ESC[4;38;5;81mWSGIRequestHandler(ESC[4;38;5;149mBaseHTTPRequestHandler):
      72  
      73      server_version = "WSGIServer/" + __version__
      74  
      75      def get_environ(self):
      76          env = self.server.base_environ.copy()
      77          env['SERVER_PROTOCOL'] = self.request_version
      78          env['SERVER_SOFTWARE'] = self.server_version
      79          env['REQUEST_METHOD'] = self.command
      80          if '?' in self.path:
      81              path,query = self.path.split('?',1)
      82          else:
      83              path,query = self.path,''
      84  
      85          env['PATH_INFO'] = urllib.parse.unquote(path, 'iso-8859-1')
      86          env['QUERY_STRING'] = query
      87  
      88          host = self.address_string()
      89          if host != self.client_address[0]:
      90              env['REMOTE_HOST'] = host
      91          env['REMOTE_ADDR'] = self.client_address[0]
      92  
      93          if self.headers.get('content-type') is None:
      94              env['CONTENT_TYPE'] = self.headers.get_content_type()
      95          else:
      96              env['CONTENT_TYPE'] = self.headers['content-type']
      97  
      98          length = self.headers.get('content-length')
      99          if length:
     100              env['CONTENT_LENGTH'] = length
     101  
     102          for k, v in self.headers.items():
     103              k=k.replace('-','_').upper(); v=v.strip()
     104              if k in env:
     105                  continue                    # skip content length, type,etc.
     106              if 'HTTP_'+k in env:
     107                  env['HTTP_'+k] += ','+v     # comma-separate multiple headers
     108              else:
     109                  env['HTTP_'+k] = v
     110          return env
     111  
     112      def get_stderr(self):
     113          return sys.stderr
     114  
     115      def handle(self):
     116          """Handle a single HTTP request"""
     117  
     118          self.raw_requestline = self.rfile.readline(65537)
     119          if len(self.raw_requestline) > 65536:
     120              self.requestline = ''
     121              self.request_version = ''
     122              self.command = ''
     123              self.send_error(414)
     124              return
     125  
     126          if not self.parse_request(): # An error code has been sent, just exit
     127              return
     128  
     129          handler = ServerHandler(
     130              self.rfile, self.wfile, self.get_stderr(), self.get_environ(),
     131              multithread=False,
     132          )
     133          handler.request_handler = self      # backpointer for logging
     134          handler.run(self.server.get_app())
     135  
     136  
     137  
     138  def demo_app(environ,start_response):
     139      from io import StringIO
     140      stdout = StringIO()
     141      print("Hello world!", file=stdout)
     142      print(file=stdout)
     143      h = sorted(environ.items())
     144      for k,v in h:
     145          print(k,'=',repr(v), file=stdout)
     146      start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')])
     147      return [stdout.getvalue().encode("utf-8")]
     148  
     149  
     150  def make_server(
     151      host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
     152  ):
     153      """Create a new WSGI server listening on `host` and `port` for `app`"""
     154      server = server_class((host, port), handler_class)
     155      server.set_app(app)
     156      return server
     157  
     158  
     159  if __name__ == '__main__':
     160      with make_server('', 8000, demo_app) as httpd:
     161          sa = httpd.socket.getsockname()
     162          print("Serving HTTP on", sa[0], "port", sa[1], "...")
     163          import webbrowser
     164          webbrowser.open('http://localhost:8000/xyz?abc')
     165          httpd.handle_request()  # serve one request, then exit