summaryrefslogtreecommitdiff
path: root/project1/proj1_s4498062/webhttp/composer.py
diff options
context:
space:
mode:
Diffstat (limited to 'project1/proj1_s4498062/webhttp/composer.py')
-rw-r--r--project1/proj1_s4498062/webhttp/composer.py53
1 files changed, 44 insertions, 9 deletions
diff --git a/project1/proj1_s4498062/webhttp/composer.py b/project1/proj1_s4498062/webhttp/composer.py
index b8b9f6a..bce6208 100644
--- a/project1/proj1_s4498062/webhttp/composer.py
+++ b/project1/proj1_s4498062/webhttp/composer.py
@@ -4,6 +4,7 @@ This module contains a composer, which can compose responses to
HTTP requests from a client.
"""
+from multiprocessing import Process, Queue
import re
import time
@@ -36,17 +37,50 @@ class ResponseComposer:
"""
response = Response()
+ q = Queue()
+
if re.search(r'\/\.\.?(\/|$)', request.uri):
- return self.serve_error(403)
+ p = Process(target=self.serve_error,
+ args=(403,), kwargs=dict(queue=q))
+ else:
+ p = Process(target=self.serve,
+ args=(request.uri,), kwargs=dict(queue=q, request=request))
+
+ p.start()
+ p.join(self.timeout)
+
+ if p.is_alive():
+ p.terminate()
+ p.join()
+
+ logging.warning('Had to kill Composer.serve')
+
+ resp = Response()
+ resp.code = 504
+ resp.set_header('Connection', 'close')
+ resp.body = 'Internal timeout'
+ resp.set_content_length()
else:
- return self.serve(request.uri, request=request)
+ try:
+ resp = q.get(False)
+ except:
+ # After a timeout, we just make the most minimalistic response
+ # here (that is, no special error files are considered).
+ resp = Response()
+ resp.code = 500
+ resp.set_header('Connection', 'close')
+ resp.body = 'This should never happen'
+ resp.set_content_length()
+
+ return resp
+
- def serve(self, uri, code=200, etag=None, request=None):
+ def serve(self, uri, code=200, etag=None, request=None, queue=None):
resp = Response()
+ req = request
try:
resource = Resource(uri)
- req = request
if req != None and (
resource.etag_match(req.get_header('If-None-Match')) or \
req.get_header('If-Match') != None and \
@@ -70,23 +104,24 @@ class ResponseComposer:
resp.set_content_length()
except FileExistError:
if code < 400:
- return self.serve_error(404)
+ self.serve_error(404, queue=queue)
else:
resp.code = code
resp.body = 'Error %d' % code
resp.set_content_length()
except FileAccessError:
- return self.serve_error(403)
+ self.serve_error(403, queue=queue)
conn = 'keep-alive'
if req != None and req.get_header('Connection') == 'close':
conn = 'close'
resp.set_header('Connection', conn)
- return resp
+ queue.put(resp)
- def serve_error(self, code):
- return self.serve(config('error%d' % code, default=None), code=code)
+ def serve_error(self, code, queue=None):
+ return self.serve(config('error%d' % code, default=None),
+ code=code, queue=queue)
def make_date_string(self):
"""Make string of date and time