diff options
Diffstat (limited to 'project1')
-rw-r--r-- | project1/proj1_s4498062/Makefile | 5 | ||||
-rw-r--r-- | project1/proj1_s4498062/webhttp/composer.py | 53 | ||||
-rw-r--r-- | project1/proj1_s4498062/webhttp/server.py | 3 |
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)
|