blob: e74f576763fa40c2976eb37c7755136f749f4c33 [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +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
Georg Brandl24420152008-05-26 16:32:26 +000013from http.server import BaseHTTPRequestHandler, HTTPServer
Thomas Wouters0e3f5912006-08-11 14:57:12 +000014import 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
40
41
42class 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
83class 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
120 else:
121 env['HTTP_'+k] = v
122 return env
123
124 def get_stderr(self):
125 return sys.stderr
126
127 def handle(self):
128 """Handle a single HTTP request"""
129
130 self.raw_requestline = self.rfile.readline()
131 if not self.parse_request(): # An error code has been sent, just exit
132 return
133
134 handler = ServerHandler(
135 self.rfile, self.wfile, self.get_stderr(), self.get_environ()
136 )
137 handler.request_handler = self # backpointer for logging
138 handler.run(self.server.get_app())
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165def demo_app(environ,start_response):
Guido van Rossum6a10e022007-08-08 17:01:45 +0000166 from io import StringIO
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000167 stdout = StringIO()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000168 print("Hello world!", file=stdout)
169 print(file=stdout)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000170 h = environ.items(); h.sort()
171 for k,v in h:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000172 print(k,'=',repr(v), file=stdout)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000173 start_response("200 OK", [('Content-Type','text/plain')])
174 return [stdout.getvalue()]
175
176
177def make_server(
178 host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
179):
180 """Create a new WSGI server listening on `host` and `port` for `app`"""
181 server = server_class((host, port), handler_class)
182 server.set_app(app)
183 return server
184
185
186if __name__ == '__main__':
187 httpd = make_server('', 8000, demo_app)
188 sa = httpd.socket.getsockname()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000189 print("Serving HTTP on", sa[0], "port", sa[1], "...")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000190 import webbrowser
191 webbrowser.open('http://localhost:8000/xyz?abc')
192 httpd.handle_request() # serve one request, then exit
193
194
195
196
197
198
199
200
201
202
203
204
205#