blob: 35b98d10d87edbc9e8c1f5e0dd1078a5db0897cc [file] [log] [blame]
Phillip J. Eby5cf565d2006-06-09 16:40:18 +00001"""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
Phillip J. Eby5cf565d2006-06-09 16:40:18 +000040class 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
Phillip J. Eby5cf565d2006-06-09 16:40:18 +000069class 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
Senthil Kumarancdabc372014-09-17 16:27:06 +0800116 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
Phillip J. Eby5cf565d2006-06-09 16:40:18 +0000124 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
Phillip J. Eby5cf565d2006-06-09 16:40:18 +0000135def 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:
Brett Cannond250c8d2008-08-04 21:30:53 +0000142 print >>stdout, k,'=', repr(v)
Phillip J. Eby5cf565d2006-06-09 16:40:18 +0000143 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__':
Phillip J. Eby5cf565d2006-06-09 16:40:18 +0000157 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
Georg Brandl62e95802013-10-14 16:52:13 +0200163 httpd.server_close()