diff --git a/resources/session02/homework/http_server.py b/resources/session02/homework/http_server.py index 84ceffe1..162d7430 100644 --- a/resources/session02/homework/http_server.py +++ b/resources/session02/homework/http_server.py @@ -1,16 +1,62 @@ +#!/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 + 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. + + python tests.py ResolveURITestCase.test_directory_resource + + python tests.py ResponseOkTestCase.test_passed_mimetype_in_response +""" + import socket import sys +import os +import mimetypes 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""" @@ -22,7 +68,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 Not Found") + resp.append("") + return "\r\n".join(resp).encode('utf8') def parse_request(request): @@ -32,10 +82,39 @@ def parse_request(request): raise NotImplementedError("We only accept GET") return uri - 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. + """ + # print("URI: {}".format(uri)) + webroot = "/webroot" + path = os.getcwd() + webroot + uri + # 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 def server(log_buffer=sys.stderr): 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)