1 """ |
|
2 A tornado-based HTTP app |
|
3 """ |
|
4 |
|
5 import tornado.web |
|
6 import tornado.httpserver |
|
7 import tornado.wsgi |
|
8 import werkzeug |
|
9 |
|
10 from pngtile import handlers |
|
11 |
|
12 class MainHandler (tornado.web.RequestHandler) : |
|
13 """ |
|
14 Main handler for the / URL, pass off requests to werkzeug-based handlers... |
|
15 """ |
|
16 |
|
17 def build_environ (self, path) : |
|
18 """ |
|
19 Yield a series of (key, value) pairs suitable for use with WSGI |
|
20 """ |
|
21 |
|
22 request = self.request |
|
23 |
|
24 hostport = request.host.split(":") |
|
25 |
|
26 if len(hostport) == 2: |
|
27 host = hostport[0] |
|
28 port = int(hostport[1]) |
|
29 else: |
|
30 host = request.host |
|
31 port = 443 if request.protocol == "https" else 80 |
|
32 |
|
33 yield "REQUEST_METHOD", request.method |
|
34 yield "SCRIPT_NAME", "" |
|
35 yield "PATH_INFO", path |
|
36 yield "QUERY_STRING", request.query |
|
37 yield "SERVER_NAME", host |
|
38 yield "SERVER_PORT", port |
|
39 |
|
40 yield "wsgi.version", (1, 0) |
|
41 yield "wsgi.url_scheme", request.protocol |
|
42 |
|
43 yield "CONTENT_TYPE", request.headers.get("Content-Type") |
|
44 yield "CONTENT_LENGTH", request.headers.get("Content-Length") |
|
45 |
|
46 for key, value in request.headers.iteritems(): |
|
47 yield "HTTP_" + key.replace("-", "_").upper(), value |
|
48 |
|
49 def get (self, path) : |
|
50 environ = dict(self.build_environ(path)) |
|
51 |
|
52 # build Request |
|
53 request = werkzeug.Request(environ) |
|
54 |
|
55 # handle |
|
56 try : |
|
57 response = handlers.handle_req(request) |
|
58 |
|
59 except werkzeug.exceptions.HTTPException, ex : |
|
60 response = ex |
|
61 |
|
62 # return |
|
63 def start_response (_status, _headers) : |
|
64 status = int(_status.split()[0]) |
|
65 headers = _headers |
|
66 |
|
67 self.set_status(status) |
|
68 |
|
69 for name, value in headers : |
|
70 self.set_header(name, value) |
|
71 |
|
72 # invoke Response |
|
73 data = response(environ, start_response) |
|
74 |
|
75 # output data |
|
76 for chunk in data : |
|
77 self.write(chunk) |
|
78 |
|
79 def build_app () : |
|
80 return tornado.web.Application([ |
|
81 # static, from $CWD/static/ |
|
82 (r"/static/(.*)", tornado.web.StaticFileHandler, dict(path = "static/")), |
|
83 |
|
84 # dir listings, image html, PNG tiles |
|
85 (r"(/.*)", MainHandler), |
|
86 ]) |
|
87 |
|
88 def build_httpserver (app, port) : |
|
89 server = tornado.httpserver.HTTPServer(app) |
|
90 server.listen(port) |
|
91 |
|
92 return server |
|
93 |
|
94 def main (port=8000) : |
|
95 """ |
|
96 Build the app, http server and run the main loop |
|
97 """ |
|
98 |
|
99 import logging |
|
100 |
|
101 logging.basicConfig(level=logging.DEBUG) |
|
102 |
|
103 app = build_app() |
|
104 server = build_httpserver(app, port) |
|
105 |
|
106 tornado.ioloop.IOLoop.instance().start() |
|
107 |
|
108 |
|