annotate bzapi_server.py @ 37:c6b41464c021 default tip

factored async web server into separate file
author Atul Varma <varmaa@toolness.com>
date Thu, 24 Dec 2009 18:34:51 -0800
parents 352f4cc55d12
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
1 import os
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
2 import sys
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
3 import re
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
4 import cgi
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
5 import logging
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
6
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
7 try:
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
8 import json
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
9 except ImportError:
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
10 import simplejson as json
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
11
37
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
12 import channels
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
13 import cosocket
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
14 from async_web_server import until_http_response_sent
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
15 from async_web_server import until_http_file_sent
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
16 from async_web_server import AsyncWebServer
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
17
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
18 class BugzillaApiApp(object):
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
19 QUERYSTRING_TEMPLATE = re.compile('([^\?]*)\?(.*)')
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
20 REDIRECT_TEMPLATE = re.compile('\/([A-Za-z0-9_]+)$')
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
21 URL_TEMPLATE = re.compile('\/([A-Za-z0-9_]+)/(.*)')
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
22 MAX_MESSAGE_SIZE = 8192
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
23 ROBOTS_TXT = "User-agent: *\r\nDisallow: /"
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
24
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
25 def __init__(self, media_dir, index_filename):
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
26 self._media_dir = media_dir
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
27 self._index_filename = index_filename
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
28
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
29 def until_request_processed(self, method, path, headers, addr):
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
30 match = self.URL_TEMPLATE.match(path)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
31
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
32 if path == '/':
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
33 yield until_http_file_sent(self._index_filename)
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
34 elif not match:
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
35 match = self.REDIRECT_TEMPLATE.match(path)
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
36 if match:
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
37 newpath = path + '/'
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
38 yield until_http_response_sent(
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
39 newpath,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
40 code = 301,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
41 additional_headers = {'Location': newpath}
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
42 )
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
43 elif path == '/robots.txt':
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
44 yield until_http_response_sent(self.ROBOTS_TXT)
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
45 else:
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
46 yield until_http_response_sent('not found',
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
47 code = 404)
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
48 else:
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
49 conv_name = match.group(1)
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
50 page = match.group(2)
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
51 if conv_name == 'status':
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
52 # TODO: Return 404 if page is non-empty.
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
53 lines = ('open connections : %d' % self._num_connections,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
54 'open timers : %d' % len(time_map))
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
55 yield until_http_response_sent('\r\n'.join(lines))
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
56 elif conv_name == 'media':
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
57 path = os.path.join(self._media_dir, *page.split('/'))
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
58 path = os.path.normpath(path)
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
59 if (path.startswith(self._media_dir) and
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
60 os.path.exists(path) and
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
61 os.path.isfile(path)):
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
62 yield until_http_file_sent(path)
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
63 else:
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
64 yield until_http_response_sent('not found',
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
65 code = 404)
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
66 else:
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
67 yield self._until_conv_request_processed(addr, headers,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
68 method, conv_name,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
69 page)
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
70
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
71 def _parse_qs(self, querystring):
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
72 querydict = {}
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
73 cgi_querydict = cgi.parse_qs(querystring)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
74 for key, value in cgi_querydict.items():
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
75 querydict[key] = cgi_querydict[key][0]
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
76 return querydict
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
77
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
78 def _until_conv_request_processed(self, addr, headers, method,
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
79 conv_name, page):
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
80 match = self.QUERYSTRING_TEMPLATE.match(page)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
81 querydict = {}
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
82 if match:
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
83 querydict.update(self._parse_qs(match.group(2)))
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
84 page = match.group(1)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
85 if page == 'listen':
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
86 logging.info("Waiting for message on channel '%s' for %s" %
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
87 (conv_name, addr))
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
88 msg = yield channels.until_message_received(conv_name)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
89 yield until_http_response_sent(
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
90 json.dumps(msg),
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
91 mimetype = 'application/json'
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
92 )
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
93 elif page == 'send':
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
94 length = int(headers.getheader('Content-Length', 0))
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
95 if length == 0 or length > self.MAX_MESSAGE_SIZE:
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
96 yield until_http_response_sent('message too large',
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
97 code = 413)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
98 else:
37
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
99 msg = yield cosocket.until_received(bytes = length)
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
100 json_msg = json.loads(msg)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
101 yield channels.until_message_sent(conv_name, json_msg)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
102 yield until_http_response_sent('sent.')
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
103 else:
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
104 yield until_http_response_sent('not found', code = 404)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
105
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
106 if __name__ == '__main__':
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
107 args = dict(ip = '127.0.0.1',
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
108 port = 8071,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
109 logfile = '',
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
110 loglevel = 'info',
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
111 media_dir = os.path.abspath('media'))
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
112
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
113 args['index_filename'] = os.path.join(args['media_dir'], 'html',
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
114 'index.html')
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
115 args['loglevel'] = getattr(logging, args['loglevel'].upper())
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
116 if args['logfile']:
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
117 logging.basicConfig(filename = args['logfile'],
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
118 level = args['loglevel'])
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
119 else:
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
120 logging.basicConfig(stream = sys.stdout,
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
121 level = args['loglevel'])
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
122
35
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
123 app = BugzillaApiApp(media_dir = args['media_dir'],
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
124 index_filename = args['index_filename'])
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
125
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
126 server = AsyncWebServer(addr = (args['ip'], args['port']),
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
127 app = app)
45d84e588d14 massive refactorings to bzapi_server.py
Atul Varma <varmaa@toolness.com>
parents: 34
diff changeset
128
34
b4fab248d1eb Added a bunch of files from http://hg.toolness.com/cosocket
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
129 logging.info("Starting server with configuration: %s" % args)
37
c6b41464c021 factored async web server into separate file
Atul Varma <varmaa@toolness.com>
parents: 36
diff changeset
130 cosocket.loop()