summaryrefslogtreecommitdiff
path: root/project1
diff options
context:
space:
mode:
Diffstat (limited to 'project1')
-rw-r--r--project1/proj1_s4498062/Makefile5
-rw-r--r--project1/proj1_s4498062/webhttp/composer.py53
-rw-r--r--project1/proj1_s4498062/webhttp/server.py3
3 files changed, 48 insertions, 13 deletions
diff --git a/project1/proj1_s4498062/Makefile b/project1/proj1_s4498062/Makefile
index a0e071a..39c4da7 100644
--- a/project1/proj1_s4498062/Makefile
+++ b/project1/proj1_s4498062/Makefile
@@ -12,7 +12,10 @@ webserver: webserver.c
$(CC) $(CCFLAGS) -o $@ $<
run: webserver
- ./webserver
+ ./$<
+
+test: webtests.py webhttp/*.py
+ python $<
clean:
rm -vf webserver webserver.c
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
diff --git a/project1/proj1_s4498062/webhttp/server.py b/project1/proj1_s4498062/webhttp/server.py
index 02ed8a6..62f1bdb 100644
--- a/project1/proj1_s4498062/webhttp/server.py
+++ b/project1/proj1_s4498062/webhttp/server.py
@@ -36,9 +36,6 @@ class ConnectionHandler(threading.Thread):
self.conn_socket.settimeout(self.timeout)
- # TODO: should not be persistent when client sends Connection: close
- # or can we safely assume that in this case the client will close the
- # transport channel, so that recv() returns something empty?
try:
while not self.done:
data = self.conn_socket.recv(4096)