1
# Written by Bram Cohen
2
# see LICENSE.txt for license information
4
from cStringIO import StringIO
7
from clock import clock
8
from gzip import GzipFile
17
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
19
months = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
20
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
23
def __init__(self, handler, connection):
24
self.handler = handler
25
self.connection = connection
29
self.donereading = False
30
self.next_func = self.read_type
33
return self.connection.get_ip()
35
def data_came_in(self, data):
36
if self.donereading or self.next_func is None:
41
i = self.buf.index('\n')
45
self.buf = self.buf[i+1:]
46
self.next_func = self.next_func(val)
49
if self.next_func is None or self.closed:
52
def read_type(self, data):
53
self.header = data.strip()
56
self.command, self.path, garbage = words
59
self.command, self.path = words
61
if self.command != 'GET':
65
if self.command not in ('HEAD', 'GET'):
68
return self.read_header
70
def read_header(self, data):
73
self.donereading = True
74
if self.headers.get('accept-encoding','').find('gzip') > -1:
75
self.encoding = 'gzip'
77
self.encoding = 'identity'
78
r = self.handler.getfunc(self, self.path, self.headers)
86
self.headers[data[:i].strip().lower()] = data[i+1:].strip()
88
print data[:i].strip() + ": " + data[i+1:].strip()
89
return self.read_header
91
def answer(self, (responsecode, responsestring, headers, data)):
94
if self.encoding == 'gzip':
95
compressed = StringIO()
96
gz = GzipFile(fileobj = compressed, mode = 'wb', compresslevel = 9)
99
cdata = compressed.getvalue()
100
if len(cdata) >= len(data):
101
self.encoding = 'identity'
104
print "Compressed: %i Uncompressed: %i\n" % (len(cdata),len(data))
106
headers['Content-Encoding'] = 'gzip'
108
# i'm abusing the identd field here, but this should be ok
109
if self.encoding == 'identity':
112
ident = self.encoding
113
self.handler.log( self.connection.get_ip(), ident, '-',
114
self.header, responsecode, len(data),
115
self.headers.get('referer','-'),
116
self.headers.get('user-agent','-') )
119
r.write('HTTP/1.0 ' + str(responsecode) + ' ' +
120
responsestring + '\r\n')
122
headers['Content-Length'] = len(data)
123
for key, value in headers.items():
124
r.write(key + ': ' + str(value) + '\r\n')
126
if self.command != 'HEAD':
128
self.connection.write(r.getvalue())
129
if self.connection.is_flushed():
130
self.connection.shutdown(1)
133
def __init__(self, getfunc, minflush):
134
self.connections = {}
135
self.getfunc = getfunc
136
self.minflush = minflush
137
self.lastflush = clock()
139
def external_connection_made(self, connection):
140
self.connections[connection] = HTTPConnection(self, connection)
142
def connection_flushed(self, connection):
143
if self.connections[connection].done:
144
connection.shutdown(1)
146
def connection_lost(self, connection):
147
ec = self.connections[connection]
151
del self.connections[connection]
153
def data_came_in(self, connection, data):
154
c = self.connections[connection]
155
if not c.data_came_in(data) and not c.closed:
156
c.connection.shutdown(1)
158
def log(self, ip, ident, username, header,
159
responsecode, length, referrer, useragent):
160
year, month, day, hour, minute, second, a, b, c = time.localtime(time.time())
161
print '%s %s %s [%02d/%3s/%04d:%02d:%02d:%02d] "%s" %i %i "%s" "%s"' % (
162
ip, ident, username, day, months[month], year, hour,
163
minute, second, header, responsecode, length, referrer, useragent)
165
if t - self.lastflush > self.minflush: