From 3586858d203ce2460cbe4cf0bdc1f56eb26503bb Mon Sep 17 00:00:00 2001 From: GerardoP Date: Wed, 26 Aug 2020 16:13:50 -0700 Subject: [PATCH 1/3] Completed assigned tasks. --- .gitignore | 1 + http_server.py | 108 ++++++++++++++++++++++++------------------------- 2 files changed, 54 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 1981ccb..7f64ed6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *pycache* *solution* *.idea* +.vscode diff --git a/http_server.py b/http_server.py index 58d7386..71a7b40 100644 --- a/http_server.py +++ b/http_server.py @@ -1,6 +1,9 @@ import socket import sys import traceback +import os +import mimetypes + def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ @@ -10,7 +13,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,77 +20,84 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"):

Welcome:

\r\n ''' """ + return b'\r\n'.join([ + b'HTTP/1.1 200 OK', + b'Content-Type: ' + mimetype, + b'', + body + ]) - # TODO: Implement response_ok - return b"" 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'Content-Type: text/plain', + b'', + b'405. You can\'t do that 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'Content-Type: text/plain', + b'', + b'404. 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. """ + method, path, version = request.split('\r\n')[0].split(' ') + if method != 'GET': + raise NotImplementedError + return path - # TODO: implement parse_request - return "" 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 - """ - - # TODO: Raise a NameError if the requested content is not present - # under webroot. - - # TODO: Fill in the appropriate content and mime_type give the path. - # See the assignment guidelines for help on "mapping mime-types", though - # you might need to create a special case for handling make_time.py - # - # 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" - + local_path = 'webroot' + path + if os.path.isdir(local_path): + files = [file_name.encode() for file_name in os.listdir(local_path)] + content = b'\r\n'.join(files) + mime_type = b'text/plain' + elif os.path.isfile(local_path): + with open(local_path, 'rb') as reader: + content = b'' + byte = reader.read(1) + while byte: + content += byte + byte = reader.read(1) + if local_path == 'webroot/make_time.py': + mime_type = b'text/plain' + else: + mime_type = mimetypes.guess_type( + os.path.normpath(local_path))[0].encode() + else: + raise NameError return content, mime_type @@ -114,30 +123,21 @@ def server(log_buffer=sys.stderr): if '\r\n\r\n' in request: break - 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) + body, mimetype = response_path(path) + response = response_ok(body, mimetype) + except NotImplementedError: + response = response_method_not_allowed() + except NameError: + response = response_not_found() conn.sendall(response) except: traceback.print_exc() finally: - conn.close() + conn.close() except KeyboardInterrupt: sock.close() @@ -149,5 +149,3 @@ def server(log_buffer=sys.stderr): if __name__ == '__main__': server() sys.exit(0) - - From 9a3120c42f69fe456f85c0303ee58234729f712c Mon Sep 17 00:00:00 2001 From: GerardoP Date: Wed, 26 Aug 2020 18:29:39 -0700 Subject: [PATCH 2/3] Completed assigned and optional tasks. --- http_server.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/http_server.py b/http_server.py index 71a7b40..87554b3 100644 --- a/http_server.py +++ b/http_server.py @@ -3,6 +3,7 @@ import traceback import os import mimetypes +import subprocess def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): @@ -79,21 +80,24 @@ def response_path(path): b"text/plain") response_path('/a_page_that_doesnt_exist.html') -> Raises a NameError """ - local_path = 'webroot' + path + temp_path = 'webroot' + path + local_path = os.path.normpath(temp_path) if os.path.isdir(local_path): files = [file_name.encode() for file_name in os.listdir(local_path)] content = b'\r\n'.join(files) mime_type = b'text/plain' elif os.path.isfile(local_path): - with open(local_path, 'rb') as reader: - content = b'' - byte = reader.read(1) - while byte: - content += byte - byte = reader.read(1) - if local_path == 'webroot/make_time.py': - mime_type = b'text/plain' + if os.path.basename(local_path) == 'make_time.py': + content = subprocess.run( + ['python', local_path], capture_output=True).stdout + mime_type = b'text/html' else: + with open(local_path, 'rb') as reader: + content = b'' + byte = reader.read(1) + while byte: + content += byte + byte = reader.read(1) mime_type = mimetypes.guess_type( os.path.normpath(local_path))[0].encode() else: From 17cc5a28d79ba247fd8a56434ea010b293d4efd4 Mon Sep 17 00:00:00 2001 From: GerardoP Date: Thu, 27 Aug 2020 10:21:51 -0700 Subject: [PATCH 3/3] Removed redundant code --- http_server.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/http_server.py b/http_server.py index 87554b3..d02bbce 100644 --- a/http_server.py +++ b/http_server.py @@ -98,8 +98,7 @@ def response_path(path): while byte: content += byte byte = reader.read(1) - mime_type = mimetypes.guess_type( - os.path.normpath(local_path))[0].encode() + mime_type = mimetypes.guess_type(local_path)[0].encode() else: raise NameError return content, mime_type