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