diff --git a/http_server.py b/http_server.py index 58d7386..7fe7b45 100644 --- a/http_server.py +++ b/http_server.py @@ -1,66 +1,74 @@ import socket import sys import traceback +import os +import mimetypes def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ returns a basic HTTP response - Ex: - response_ok( - b"

Welcome:

", - b"text/html" - ) -> - - b''' - HTTP/1.1 200 OK\r\n - Content-Type: text/html\r\n - \r\n -

Welcome:

\r\n - ''' + Ex: + response_ok( + b"

Welcome:

", + b"text/html" + ) -> + + b''' + HTTP/1.1 200 OK\r\n + Content-Type: text/html\r\n + \r\n +

Welcome:

\r\n + ''' """ # TODO: Implement response_ok - return b"" + return b"\r\n".join([ + b"HTTP/1.1 200 OK", + b"Content-Type: " + mimetype, + b"",body + ]) def response_method_not_allowed(): """Returns a 405 Method Not Allowed response""" # TODO: Implement response_method_not_allowed - return b"" + return b"\r\n".join([b"HTTP/1.1 405 Method Not Allowed"]) def response_not_found(): """Returns a 404 Not Found response""" # TODO: Implement response_not_found - return b"" + return b"\r\n".join([b"HTTP/1.1 404 Not Found"]) def parse_request(request): """ Given the content of an HTTP request, returns the path of that request. - This server only handles GET requests, so this method shall raise a - NotImplementedError if the method of the request is not GET. + This server only handles GET requests, so this method shall raise a + NotImplementedError if the method of the request is not GET. """ - + method, path, version = request.split("\r\n")[0].split(" ") + if method != "GET": + raise NotImplementedError # TODO: implement parse_request - return "" + return path def response_path(path): """ This method should return appropriate content and a mime type. - If the requested path is a directory, then the content should be a - plain-text listing of the contents with mimetype `text/plain`. + If the requested path is a directory, then the content should be a + plain-text listing of the contents with mimetype `text/plain`. - If the path is a file, it should return the contents of that file - and its correct mimetype. + If the path is a file, it should return the contents of that file + and its correct mimetype. - If the path does not map to a real location, it should raise an - exception that the server can catch to return a 404 response. + If the path does not map to a real location, it should raise an + exception that the server can catch to return a 404 response. - Ex: + Ex: response_path('/a_web_page.html') -> (b"

North Carolina...", b"text/html") @@ -85,9 +93,27 @@ def response_path(path): # If the path is "make_time.py", then you may OPTIONALLY return the # result of executing `make_time.py`. But you need only return the # CONTENTS of `make_time.py`. - - content = b"not implemented" - mime_type = b"not implemented" + + + + file_path = os.path.join(os.getcwd(), 'webroot', path.strip('/')) + + # If the path indicates a directory: + if os.path.isdir(file_path): + content = "\n".join(os.listdir(file_path)).encode('utf8') + mime_type = b"text/plain" + return content, mime_type + + # If the path indicates a file: + elif os.path.exists(file_path): + mime_type = mimetypes.guess_type(file_path)[0].encode('utf8') + with open(file_path, "br") as f: + content = f.read() + return content, mime_type + + # If the path does not indicate an existing directory or file: + else: + raise NameError return content, mime_type @@ -114,30 +140,37 @@ def server(log_buffer=sys.stderr): if '\r\n\r\n' in request: break - + print("Request received:\n{}\n\n".format(request)) + try: + path = parse_request(request) + + # TODO: Use parse_request to retrieve the path from the request. - # TODO: Use parse_request to retrieve the path from the request. + # TODO: Use response_path to retrieve the content and the mimetype, + # based on the request path. - # TODO: Use response_path to retrieve the content and the mimetype, - # based on the request path. + # TODO; If parse_request raised a NotImplementedError, then let + # response be a method_not_allowed response. If response_path raised + # a NameError, then let response be a not_found response. Else, + # use the content and mimetype from response_path to build a + # response_ok. + content, mimetype = response_path(path) + except NotImplementedError: + response = response_method_not_allowed() + conn.sendall(response) + except NameError: + response = response_not_found() + conn.sendall(response) - # TODO; If parse_request raised a NotImplementedError, then let - # response be a method_not_allowed response. If response_path raised - # a NameError, then let response be a not_found response. Else, - # use the content and mimetype from response_path to build a - # response_ok. - response = response_ok( - body=b"Welcome to my web server", - mimetype=b"text/plain" - ) + response = response_ok(content, mimetype) conn.sendall(response) except: traceback.print_exc() finally: - conn.close() + conn.close() except KeyboardInterrupt: sock.close()