From 1d010e73089a9e1910bfc416c5c2a1a3fba11fb4 Mon Sep 17 00:00:00 2001 From: pvosper Date: Sun, 22 Jan 2017 07:15:48 -0800 Subject: [PATCH 1/4] WIP: Just getting started --- resources/session02/http_server.py | 43 ++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/resources/session02/http_server.py b/resources/session02/http_server.py index d5aaf480..02dcbc6e 100644 --- a/resources/session02/http_server.py +++ b/resources/session02/http_server.py @@ -16,16 +16,15 @@ def server(log_buffer=sys.stderr): conn, addr = sock.accept() # blocking try: print('connection - {0}:{1}'.format(*addr), file=log_buffer) + request = "" while True: - data = conn.recv(16) - print('received "{0}"'.format(data), file=log_buffer) - if data: - print('sending data back to client', file=log_buffer) - conn.sendall(data) - else: - msg = 'no more data from {0}:{1}'.format(*addr) - print(msg, log_buffer) + data = conn.recv(1024) + request += data.decode('utf8') + if len(data) < 1024: break + print('sending response', file=log_buffer) + response = response_ok() + conn.sendall(response) finally: conn.close() @@ -34,6 +33,34 @@ def server(log_buffer=sys.stderr): return +def response_ok(): + """this function returns the simple http response""" + + resp = [] + resp.append(b"HTTP/1.1 200 OK") + resp.append(b"Content-Type: text/plain") + resp.append(b"") + resp.append(b"this is a pretty minimal response") + + return b"\r\n".join(resp) + + +def parse_request(request): + first_line = request.split("\r\n")[0] + method, uri, protocol = first_line.split() + if method != "GET": + raise NotImplementedError("We only accept GET") + print('request is okay', file=sys.stderr) + + +def response_method_not_allowed(): + """returns a 405 Method Not Allowed response""" + resp = [] + resp.append(b"HTTP/1.1 405 Method Not Allowed") + resp.append(b"") + return b"\r\n".join(resp) + + if __name__ == '__main__': server() sys.exit(0) From 22c1b9bfa7c6eb148926c3ae992f961b1ab1230e Mon Sep 17 00:00:00 2001 From: pvosper Date: Sun, 22 Jan 2017 09:59:59 -0800 Subject: [PATCH 2/4] WIP: First test passing --- resources/session02/homework/http_server.py | 66 ++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/resources/session02/homework/http_server.py b/resources/session02/homework/http_server.py index 84ceffe1..0feecfa8 100644 --- a/resources/session02/homework/http_server.py +++ b/resources/session02/homework/http_server.py @@ -1,5 +1,42 @@ +#!/usr/bin/env python3 + +""" +Homework + Take the following steps one at a time. Run the tests in + assignments/session02/homework between to ensure that you are getting it + right. + + 1) Complete the stub resolve_uri function so that it handles looking up + resources on disk using the URI returned by parse_request. + + 2) Make sure that if the URI does not map to a file that exists, it raises + an appropriate error for our server to handle. + + 3) Complete the response_not_found function stub so that it returns a 404 + response. + + 4) Update response_ok so that it uses the values returned by resolve_uri by + the URI. (these have already been added to the function signature) + You'll plug those values into the response you generate in the way + required by the protocol + + @maria: + + When starting the homework, start by first getting just this test to pass: + ```python tests.py ResolveURITestCase.test_directory_resource``` + + You might find the test to look confusing at first. It is testing the + function resolve_uri (the function above this test assigns + call_function_under_test to this function). + + It is expecting that this function is going to return two objects, + + Look at the test to figure out what these objects should be. +""" + import socket import sys +import os def response_ok(body=b"this is a pretty minimal response", mimetype=b"text/plain"): @@ -32,10 +69,35 @@ def parse_request(request): raise NotImplementedError("We only accept GET") return uri - +# It is expecting that this function is going to return two objects, +# Look at the test to figure out what these objects should be. +# 1) Complete the stub resolve_uri function so that it handles looking up +# resources on disk using the URI returned by parse_request. +# actual_body, actual_mimetype def resolve_uri(uri): """This method should return appropriate content and a mime type""" - return b"still broken", b"text/plain" + """Your resolve_uri function will need to accomplish the following tasks: + + It should take a URI as the sole argument + It should map the pathname represented by the URI to a filesystem location. + It should have a 'home directory', and look only in that location. + If the URI is a directory, it should return a plain-text listing of the + directory contents and the mimetype text/plain. + If the URI is a file, it should return the contents of that file and its + correct mimetype. + If the URI does not map to a real location, it should raise an exception + that the server can catch to return a 404 response. + """ + content = b"" + if uri[-1] == "/": + path = os.getcwd() + '//webroot' + uri + content = os.listdir(path) + content = ';'.join(content) + # .encode('utf-8') + # with open(filepath) as f: + # content = f.readlines() + # return b"still broken", b"text/plain" + return content.encode('utf-8'), b"text/plain" def server(log_buffer=sys.stderr): From fe3af6eeb047d316441b42a3d7e8ad4b4d7d4b39 Mon Sep 17 00:00:00 2001 From: pvosper Date: Tue, 24 Jan 2017 06:29:59 -0800 Subject: [PATCH 3/4] WIP: 7 failers, which is progress at least --- resources/session02/homework/http_server.py | 32 +++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/resources/session02/homework/http_server.py b/resources/session02/homework/http_server.py index 0feecfa8..9a28eeb3 100644 --- a/resources/session02/homework/http_server.py +++ b/resources/session02/homework/http_server.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 """ +FAILED (failures=8, errors=4) +FAILED (failures=10) Homework Take the following steps one at a time. Run the tests in assignments/session02/homework between to ensure that you are getting it @@ -37,6 +39,7 @@ import socket import sys import os +import mimetypes def response_ok(body=b"this is a pretty minimal response", mimetype=b"text/plain"): @@ -59,7 +62,11 @@ def response_method_not_allowed(): def response_not_found(): """returns a 404 Not Found response""" - return b"" + # return b"" + resp = [] + resp.append("HTTP/1.1 404 Method Not found") + resp.append("") + return "\r\n".join(resp).encode('utf8') def parse_request(request): @@ -88,16 +95,25 @@ def resolve_uri(uri): If the URI does not map to a real location, it should raise an exception that the server can catch to return a 404 response. """ - content = b"" - if uri[-1] == "/": - path = os.getcwd() + '//webroot' + uri + print("URI: {}".format(uri)) + webroot = "/webroot" + path = os.getcwd() + webroot + uri + mimetype = "text/plain" + if os.path.isfile(path): + print("os.path.isfile({})".format(path)) + with open(path, "rb") as f: + print("Open f") + content = f.read() + mimetype = mimetypes.guess_type(path)[0] + print("mimetype: {}".format(mimetype)) + if os.path.isdir(path): + print("os.path.isdir({})".format(path)) content = os.listdir(path) content = ';'.join(content) - # .encode('utf-8') - # with open(filepath) as f: - # content = f.readlines() + content = content.encode("utf-8") + # return b"still broken", b"text/plain" - return content.encode('utf-8'), b"text/plain" + return content, mimetype.encode('utf-8') def server(log_buffer=sys.stderr): From a09c1d346e0f7411e3ac6922cc23e23e57356fae Mon Sep 17 00:00:00 2001 From: pvosper Date: Tue, 24 Jan 2017 12:25:11 -0800 Subject: [PATCH 4/4] All tests passing - declaring it a miracle --- resources/session02/homework/http_server.py | 51 +++++++++++---------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/resources/session02/homework/http_server.py b/resources/session02/homework/http_server.py index 9a28eeb3..162d7430 100644 --- a/resources/session02/homework/http_server.py +++ b/resources/session02/homework/http_server.py @@ -34,6 +34,10 @@ It is expecting that this function is going to return two objects, Look at the test to figure out what these objects should be. + + python tests.py ResolveURITestCase.test_directory_resource + + python tests.py ResponseOkTestCase.test_passed_mimetype_in_response """ import socket @@ -46,11 +50,13 @@ def response_ok(body=b"this is a pretty minimal response", mimetype=b"text/plain """returns a basic HTTP response""" resp = [] resp.append(b"HTTP/1.1 200 OK") - resp.append(b"Content-Type: text/plain") + # resp.append(b"Content-Type: text/plain") + resp.append(b"Content-Type: " + mimetype) resp.append(b"") - resp.append(b"this is a pretty minimal response") - return b"\r\n".join(resp) + resp.append(body) + # resp.append(b"this is a pretty minimal response") + return b"\r\n".join(resp) def response_method_not_allowed(): """returns a 405 Method Not Allowed response""" @@ -64,7 +70,7 @@ def response_not_found(): """returns a 404 Not Found response""" # return b"" resp = [] - resp.append("HTTP/1.1 404 Method Not found") + resp.append("HTTP/1.1 404 Not Found") resp.append("") return "\r\n".join(resp).encode('utf8') @@ -76,11 +82,6 @@ def parse_request(request): raise NotImplementedError("We only accept GET") return uri -# It is expecting that this function is going to return two objects, -# Look at the test to figure out what these objects should be. -# 1) Complete the stub resolve_uri function so that it handles looking up -# resources on disk using the URI returned by parse_request. -# actual_body, actual_mimetype def resolve_uri(uri): """This method should return appropriate content and a mime type""" """Your resolve_uri function will need to accomplish the following tasks: @@ -95,25 +96,25 @@ def resolve_uri(uri): If the URI does not map to a real location, it should raise an exception that the server can catch to return a 404 response. """ - print("URI: {}".format(uri)) + # print("URI: {}".format(uri)) webroot = "/webroot" path = os.getcwd() + webroot + uri - mimetype = "text/plain" - if os.path.isfile(path): - print("os.path.isfile({})".format(path)) - with open(path, "rb") as f: - print("Open f") - content = f.read() - mimetype = mimetypes.guess_type(path)[0] - print("mimetype: {}".format(mimetype)) - if os.path.isdir(path): - print("os.path.isdir({})".format(path)) - content = os.listdir(path) - content = ';'.join(content) - content = content.encode("utf-8") - + # content = b"" # Adding this fails additional test + mimetype = b"text/plain" + try: + if os.path.isfile(path): + with open(path, "rb") as f: + content = f.read() + mimetype = mimetypes.guess_type(path)[0].encode('utf-8') + if os.path.isdir(path): + content = os.listdir(path) + content = ';'.join(content) + content = content.encode("utf-8") + except: + # raise NameError("File not found") + return response_not_found() # return b"still broken", b"text/plain" - return content, mimetype.encode('utf-8') + return content, mimetype def server(log_buffer=sys.stderr):