8 class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer, object):
10 allow_reuse_address = 1
12 def __init__(self, *args, **kwargs):
15 # before reading request headers
17 # before reading request body
19 # before setting response status and headers
21 # before sending response body
23 # before returning from handler (thus setting response EOF)
26 super(Server, self).__init__(*args, **kwargs)
28 def setdelays(self, **kwargs):
29 """In future requests, induce delays at the given checkpoints."""
30 for (k, v) in kwargs.iteritems():
31 self.delays.get(k) # NameError if unknown key
34 def _sleep_at_least(self, seconds):
35 """Sleep for given time, even if signals are received."""
36 wake = time.time() + seconds
40 todo = wake - time.time()
42 def _do_delay(self, k):
43 self._sleep_at_least(self.delays[k])
46 class Handler(BaseHTTPServer.BaseHTTPRequestHandler, object):
47 def handle(self, *args, **kwargs):
48 self.server._do_delay('request')
49 return super(Handler, self).handle(*args, **kwargs)
52 self.server._do_delay('response')
53 r = re.search(r'[0-9a-f]{32}', self.path)
55 return self.send_response(422)
57 if datahash not in self.server.store:
58 return self.send_response(404)
59 self.send_response(200)
60 self.send_header('Content-type', 'application/octet-stream')
62 self.server._do_delay('response_body')
63 self.wfile.write(self.server.store[datahash])
64 self.server._do_delay('response_close')
67 self.server._do_delay('request_body')
69 # The comments at https://bugs.python.org/issue1491 implies that Python
70 # 2.7 BaseHTTPRequestHandler was patched to support 100 Continue, but
71 # reading the actual code that ships in Debian it clearly is not, so we
72 # need to send the response on the socket directly.
74 self.wfile.write("%s %d %s\r\n\r\n" %
75 (self.protocol_version, 100, "Continue"))
77 data = self.rfile.read(int(self.headers.getheader('content-length')))
78 datahash = hashlib.md5(data).hexdigest()
79 self.server.store[datahash] = data
80 self.server._do_delay('response')
81 self.send_response(200)
82 self.send_header('Content-type', 'text/plain')
84 self.server._do_delay('response_body')
85 self.wfile.write(datahash + '+' + str(len(data)))
86 self.server._do_delay('response_close')
88 def log_request(self, *args, **kwargs):
89 if os.environ.get('ARVADOS_DEBUG', None):
90 super(Handler, self).log_request(*args, **kwargs)
92 def finish(self, *args, **kwargs):
93 """Ignore exceptions, notably "Broken pipe" when client times out."""
95 return super(Handler, self).finish(*args, **kwargs)
99 def handle_one_request(self, *args, **kwargs):
100 """Ignore exceptions, notably "Broken pipe" when client times out."""
102 return super(Handler, self).handle_one_request(*args, **kwargs)