diff --git a/http_server.py b/http_server.py index 58d7386..4ee3cea 100644 --- a/http_server.py +++ b/http_server.py @@ -1,6 +1,12 @@ import socket import sys import traceback +import mimetypes + +import os +from pathlib import Path + +import subprocess def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ @@ -10,7 +16,6 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): b"

Welcome:

", b"text/html" ) -> - b''' HTTP/1.1 200 OK\r\n Content-Type: text/html\r\n @@ -18,63 +23,67 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"):

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", + b"", + b"Not allowed on this server!" + ]) 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", + b"", + b"Page 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. """ - - # TODO: implement parse_request - return "" + method, path, version = request.split("\r\n")[0].split(" ") + if method not in "GET": + raise NotImplementedError + + 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 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. - Ex: response_path('/a_web_page.html') -> (b"

North Carolina...", b"text/html") - response_path('/images/sample_1.png') -> (b"A12BCF...", # contents of sample_1.png b"image/png") - response_path('/') -> (b"images/, a_web_page.html, make_type.py,...", b"text/plain") - response_path('/a_page_that_doesnt_exist.html') -> Raises a NameError - """ + content = b"\r\n" + # TODO: Raise a NameError if the requested content is not present # under webroot. @@ -85,9 +94,25 @@ 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`. + path = Path(f'./webroot{path}') + + if not os.path.exists(path): + raise NameError + elif os.path.isdir(path): + mime_type = b"text/plain" + content = "\r\n".join(os.listdir(path)).encode() + elif os.path.isfile(path): + if path.suffix == '.py': + content = subprocess.check_output([sys.executable, path, ""]) + mime_type = b'text/plain' + else: + mime_type = mimetypes.guess_type(path)[0].encode() + content = open(path,'rb').read() + + - content = b"not implemented" - mime_type = b"not implemented" + # content = b"not implemented" + # mime_type = b"not implemented" return content, mime_type @@ -119,19 +144,29 @@ def server(log_buffer=sys.stderr): print("Request received:\n{}\n\n".format(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; 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" - ) + try: + path = parse_request(request) + + # TODO: Use response_path to retrieve the content and the mimetype, + # based on the request path. + + content, mimetype = response_path(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. + + response = response_ok( + body = content, + mimetype= mimetype + ) + except NotImplementedError: + response = response_method_not_allowed() + + except NameError: + response = response_not_found() conn.sendall(response) except: @@ -148,6 +183,4 @@ def server(log_buffer=sys.stderr): if __name__ == '__main__': server() - sys.exit(0) - - + sys.exit(0) \ No newline at end of file