From 0c617ce8137f8d7cee8a4d30828115c6727e56f8 Mon Sep 17 00:00:00 2001 From: mmanc125uw Date: Thu, 10 Sep 2020 10:29:22 -0400 Subject: [PATCH 1/6] sp_py230 lesson3, TDD test stubs --- do_test_integration.bat | 1 + http_server.py | 9 ++++++++- tests.py | 20 ++++++++++---------- unit-tests.py | 14 +++++++------- 4 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 do_test_integration.bat diff --git a/do_test_integration.bat b/do_test_integration.bat new file mode 100644 index 0000000..29e8596 --- /dev/null +++ b/do_test_integration.bat @@ -0,0 +1 @@ +python -m unittest -vv tests.py diff --git a/http_server.py b/http_server.py index 58d7386..439be18 100644 --- a/http_server.py +++ b/http_server.py @@ -20,7 +20,14 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ # TODO: Implement response_ok - return b"" + #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""" diff --git a/tests.py b/tests.py index 21da57e..88fcb2a 100644 --- a/tests.py +++ b/tests.py @@ -35,7 +35,7 @@ def get_response(self, url): return response - def test_post_yields_method_not_allowed(self): + def xtest_post_yields_method_not_allowed(self): """ Sending a POST request should yield a 405 Method Not Allowed response """ @@ -50,7 +50,7 @@ def test_post_yields_method_not_allowed(self): self.assertEqual(response.getcode(), 405) - def test_get_sample_text_content(self): + def xtest_get_sample_text_content(self): """ A call to /sample.txt returns the correct body """ @@ -67,7 +67,7 @@ def test_get_sample_text_content(self): with open(local_path, 'rb') as f: self.assertEqual(f.read(), response.read(), error_comment) - def test_get_sample_text_mime_type(self): + def xtest_get_sample_text_mime_type(self): """ A call to /sample.txt returns the correct mimetype """ @@ -81,7 +81,7 @@ def test_get_sample_text_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'text/plain', error_comment) - def test_get_sample_scene_balls_jpeg(self): + def xtest_get_sample_scene_balls_jpeg(self): """ A call to /images/Sample_Scene_Balls.jpg returns the correct body """ @@ -98,7 +98,7 @@ def test_get_sample_scene_balls_jpeg(self): with open(local_path, 'rb') as f: self.assertEqual(f.read(), response.read(), error_comment) - def test_get_sample_scene_balls_jpeg_mime_type(self): + def xtest_get_sample_scene_balls_jpeg_mime_type(self): """ A call to /images/Sample_Scene_Balls.jpg returns the correct mimetype """ @@ -112,7 +112,7 @@ def test_get_sample_scene_balls_jpeg_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'image/jpeg', error_comment) - def test_get_sample_1_png(self): + def xtest_get_sample_1_png(self): """ A call to /images/sample_1.png returns the correct body """ @@ -129,7 +129,7 @@ def test_get_sample_1_png(self): with open(local_path, 'rb') as f: self.assertEqual(f.read(), response.read(), error_comment) - def test_get_sample_1_png_mime_type(self): + def xtest_get_sample_1_png_mime_type(self): """ A call to /images/sample_1.png returns the correct mimetype """ @@ -143,7 +143,7 @@ def test_get_sample_1_png_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'image/png', error_comment) - def test_get_404(self): + def xtest_get_404(self): """ A call to /asdf.txt (a file which does not exist in webroot) yields a 404 error """ @@ -156,7 +156,7 @@ def test_get_404(self): self.assertEqual(response.getcode(), 404, error_comment) - def test_images_index(self): + def xtest_images_index(self): """ A call to /images/ yields a list of files in the images directory """ @@ -172,7 +172,7 @@ def test_images_index(self): for path in os.listdir(local_path): self.assertIn(path, body, error_comment) - def test_root_index(self): + def xtest_root_index(self): """ A call to / yields a list of files in the images directory """ diff --git a/unit-tests.py b/unit-tests.py index a0c657a..ef3da5c 100644 --- a/unit-tests.py +++ b/unit-tests.py @@ -5,7 +5,7 @@ class TestCase(unittest.TestCase): - def test_response_ok(self): + def xtest_response_ok(self): mimetype = b"image/bmp" body = b"foo" @@ -21,21 +21,21 @@ def test_response_ok(self): str_header.splitlines()[0]) self.assertIn("Content-Type: " + mimetype.decode(), str_header) - def test_response_method_not_allowed(self): + def xtest_response_method_not_allowed(self): response = http_server.response_method_not_allowed() str_response = response.decode() self.assertEqual("HTTP/1.1 405 Method Not Allowed", str_response.splitlines()[0]) - def test_response_not_found(self): + def xtest_response_not_found(self): response = http_server.response_not_found() str_response = response.decode() self.assertEqual("HTTP/1.1 404 Not Found", str_response.splitlines()[0]) - def test_parse_request_bad_method(self): + def xtest_parse_request_bad_method(self): request_head = "POST /foo HTTP/1.1" with self.assertRaises(NotImplementedError): @@ -47,7 +47,7 @@ def test_parse_request(self): self.assertEqual(path, http_server.parse_request(request_head)) - def test_response_path_file(self): + def xtest_response_path_file(self): path = "/a_web_page.html" content, mime_type = http_server.response_path(path) @@ -57,7 +57,7 @@ def test_response_path_file(self): with open(os.path.join("webroot", "a_web_page.html"), "rb") as f: self.assertEqual(f.read(), content) - def test_response_path_dir(self): + def xtest_response_path_dir(self): path = "/" content, mime_type = http_server.response_path(path) @@ -67,7 +67,7 @@ def test_response_path_dir(self): self.assertIn(b"sample.txt", content) self.assertIn(b"a_web_page.html", content) - def test_response_path_not_found(self): + def xtest_response_path_not_found(self): path = "/foo/bar/baz/doesnt/exist" with self.assertRaises(NameError): From c725b3a74e6d42939b1b793828dc67f900724033 Mon Sep 17 00:00:00 2001 From: mmanc125uw Date: Thu, 10 Sep 2020 10:52:42 -0400 Subject: [PATCH 2/6] sp_py230 lesson3, parse_request --- go_run_server.bat | 1 + http_server.py | 69 ++++++++++++++++++++++++----------------------- tests.py | 2 +- 3 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 go_run_server.bat diff --git a/go_run_server.bat b/go_run_server.bat new file mode 100644 index 0000000..202b1cf --- /dev/null +++ b/go_run_server.bat @@ -0,0 +1 @@ +start python -u http_server.py diff --git a/http_server.py b/http_server.py index 439be18..c2e77ed 100644 --- a/http_server.py +++ b/http_server.py @@ -5,22 +5,10 @@ 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 - ''' """ - # TODO: Implement response_ok - #return b"" + # DONE: Implement response_ok + return b"\r\n".join([ b"HTTP/1.1 200 OK", b"Content-Type: " + mimetype, @@ -32,8 +20,13 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): def response_method_not_allowed(): """Returns a 405 Method Not Allowed response""" - # TODO: Implement response_method_not_allowed - return b"" + # DONE: Implement response_method_not_allowed + return b"\r\n".join([ + b"HTTP/1.1 405 Method Not Allowed", + b"", + b"You can't do that on this server!" + ]) + def response_not_found(): @@ -51,8 +44,14 @@ def parse_request(request): NotImplementedError if the method of the request is not GET. """ - # TODO: implement parse_request - return "" + # DONE: implement parse_request + + method, path, version = request.split("\r\n")[0].split(" ") + + if method != "GET": + raise NotImplementedError + + return path def response_path(path): """ @@ -125,21 +124,25 @@ 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: + # DONE: Use parse_request to retrieve the path from the request. + path = parse_request(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" + ) + except NotImplementedError: + response = response_method_not_allowed() + conn.sendall(response) except: traceback.print_exc() diff --git a/tests.py b/tests.py index 88fcb2a..195310c 100644 --- a/tests.py +++ b/tests.py @@ -35,7 +35,7 @@ def get_response(self, url): return response - def xtest_post_yields_method_not_allowed(self): + def test_post_yields_method_not_allowed(self): """ Sending a POST request should yield a 405 Method Not Allowed response """ From 7468fe0d20aad7885ce5a42f705ad4acedff9cfb Mon Sep 17 00:00:00 2001 From: mmanc125uw Date: Thu, 10 Sep 2020 18:40:05 -0400 Subject: [PATCH 3/6] sp_py230 lesson3, testing mime --- http_server.py | 125 ++++++++++++++++++++++++++++++++++++++++++++----- tests.py | 11 ++--- 2 files changed, 118 insertions(+), 18 deletions(-) diff --git a/http_server.py b/http_server.py index c2e77ed..704c0a5 100644 --- a/http_server.py +++ b/http_server.py @@ -1,6 +1,28 @@ import socket import sys import traceback +import os +import mimetypes + + +def response_ok_AA(body=b"This is a minimal response", mimetype=b"text/plain"): + """ + returns a basic HTTP response + """ + + # DONE: Implement response_ok + + print("***MMM response_ok, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") + #print("***MMM response_ok, response body =" + str(body)) + + + return b"\r\n".join([ + b"HTTP/1.1 200 OK", + b"Content-Type: " + mimetype, + b"", + body + ]) + def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ @@ -9,11 +31,15 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): # DONE: Implement response_ok + print("***MMM response_ok, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") + #print("***MMM response_ok, response body =" + str(body)) + + return b"\r\n".join([ b"HTTP/1.1 200 OK", b"Content-Type: " + mimetype, b"", - body, + body ]) @@ -24,7 +50,7 @@ def response_method_not_allowed(): return b"\r\n".join([ b"HTTP/1.1 405 Method Not Allowed", b"", - b"You can't do that on this server!" + b"You can't do that on this server, 405 error Method Not Allowed!" ]) @@ -33,7 +59,11 @@ 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 Method Not Found", + b"", + b"You can't do that on this server, 404 error Resource Name Not Found!" + ]) def parse_request(request): @@ -50,7 +80,8 @@ def parse_request(request): if method != "GET": raise NotImplementedError - + + print("***MMM parse_request path= " + path) return path def response_path(path): @@ -81,9 +112,60 @@ def response_path(path): """ - # TODO: Raise a NameError if the requested content is not present + print("aaa") + + content = b"not implemented" + mime_type = b"not implemented" + + # DONE: Raise a NameError if the requested content is not present # under webroot. + print("bbb") + + fps = ('webroot\\' + path) + + status_isfile = os.path.isfile('webroot\\' + path) + print("response_path isfile status = " + str(status_isfile)) + + print("ccc") + + status_isdir = os.path.isdir('webroot\\' + path) + print("response_path isdir status = " + str(status_isdir)) + + print("ddd") + + if ( (status_isfile == False) and (status_isdir == False) ): + print("raise nameerror") + raise NameError + + if (status_isfile): + + mime_type=b"text/plain" + + print("***MMM resource is a file fps =" + fps) + + f=open(fps, "r") + contents =f.read() + print("***MMM file contents =" + contents) + content=contents.encode('utf-8') + + filename, file_extension = os.path.splitext(fps) + print(f"***MMM filename={filename}, extenstion={file_extension}") + + if (file_extension == ".html"): + mime_type=b"text/html" + + elif (status_isdir): + ary_files = os.listdir(fps) + print(f"***MMM list of files in dir {ary_files}") + str_files = '\n'.join(ary_files) + content = str_files.encode('utf-8') + mime_type=b"text/plain" + + + print("***MMM file content encoded =" + str(content)) + + # 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 @@ -92,8 +174,8 @@ def response_path(path): # 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" + #content = b"not implemented" + #mime_type = b"not implemented" return content, mime_type @@ -115,12 +197,16 @@ def server(log_buffer=sys.stderr): request = '' while True: + #print("11111") data = conn.recv(1024) + #print("22222") request += data.decode('utf8') if '\r\n\r\n' in request: + #print("55555") break + #print("44444") print("Request received:\n{}\n\n".format(request)) @@ -128,18 +214,32 @@ def server(log_buffer=sys.stderr): # DONE: Use parse_request to retrieve the path from the request. path = parse_request(request) - # TODO: Use response_path to retrieve the content and the mimetype, + # DONE: Use response_path to retrieve the content and the mimetype, # based on the request path. + print("call response_path") + content, mime_type = response_path(path) + #print("***MMM response content encoded =" + str(content)) + print("***MMM 1111111111111111111111111") + # 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( + # body=b"Welcome to my web server", + # mimetype=b"text/plain" + #) + + response = response_ok_AA(content, mime_type) + + print("***MMM ***********************") + #print("88888 response = " + str(response)) + + except NameError: + response = response_not_found() except NotImplementedError: response = response_method_not_allowed() @@ -147,6 +247,7 @@ def server(log_buffer=sys.stderr): except: traceback.print_exc() finally: + print("***MMM closing connection") conn.close() except KeyboardInterrupt: diff --git a/tests.py b/tests.py index 195310c..5315de3 100644 --- a/tests.py +++ b/tests.py @@ -35,7 +35,7 @@ def get_response(self, url): return response - def test_post_yields_method_not_allowed(self): + def ZZtest_post_yields_method_not_allowed(self): """ Sending a POST request should yield a 405 Method Not Allowed response """ @@ -143,7 +143,7 @@ def xtest_get_sample_1_png_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'image/png', error_comment) - def xtest_get_404(self): + def ZZtest_get_404(self): """ A call to /asdf.txt (a file which does not exist in webroot) yields a 404 error """ @@ -153,10 +153,9 @@ def xtest_get_404(self): error_comment = "Error encountered while visiting " + web_path response = self.get_response(web_path) - self.assertEqual(response.getcode(), 404, error_comment) - def xtest_images_index(self): + def ZZtest_images_index(self): """ A call to /images/ yields a list of files in the images directory """ @@ -172,7 +171,7 @@ def xtest_images_index(self): for path in os.listdir(local_path): self.assertIn(path, body, error_comment) - def xtest_root_index(self): + def test_root_index(self): """ A call to / yields a list of files in the images directory """ @@ -188,7 +187,7 @@ def xtest_root_index(self): for path in os.listdir(local_path): self.assertIn(path, body, error_comment) - def test_ok_response_at_root_index(self): + def ZZtest_ok_response_at_root_index(self): """ A call to / at least yields a 200 OK response """ From 347de4e73f0385d6d65e6fd92393b1b733884233 Mon Sep 17 00:00:00 2001 From: mmanc125uw Date: Sat, 12 Sep 2020 07:01:55 -0400 Subject: [PATCH 4/6] sp_py230, lesson3, initial bin read for png --- http_server.py | 129 +++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 69 deletions(-) diff --git a/http_server.py b/http_server.py index 704c0a5..68d9a0f 100644 --- a/http_server.py +++ b/http_server.py @@ -5,25 +5,6 @@ import mimetypes -def response_ok_AA(body=b"This is a minimal response", mimetype=b"text/plain"): - """ - returns a basic HTTP response - """ - - # DONE: Implement response_ok - - print("***MMM response_ok, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") - #print("***MMM response_ok, response body =" + str(body)) - - - return b"\r\n".join([ - b"HTTP/1.1 200 OK", - b"Content-Type: " + mimetype, - b"", - body - ]) - - def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ returns a basic HTTP response @@ -58,7 +39,7 @@ def response_method_not_allowed(): def response_not_found(): """Returns a 404 Not Found response""" - # TODO: Implement response_not_found + # DONE: Implement response_not_found return b"\r\n".join([ b"HTTP/1.1 404 Method Not Found", b"", @@ -117,12 +98,10 @@ def response_path(path): content = b"not implemented" mime_type = b"not implemented" - # DONE: Raise a NameError if the requested content is not present - # under webroot. - print("bbb") fps = ('webroot\\' + path) + print("response_path fps = " + str(fps)) status_isfile = os.path.isfile('webroot\\' + path) print("response_path isfile status = " + str(status_isfile)) @@ -134,6 +113,8 @@ def response_path(path): print("ddd") + # DONE: Raise a NameError if the requested content is not present + # under webroot. if ( (status_isfile == False) and (status_isdir == False) ): print("raise nameerror") raise NameError @@ -144,17 +125,30 @@ def response_path(path): print("***MMM resource is a file fps =" + fps) - f=open(fps, "r") - contents =f.read() - print("***MMM file contents =" + contents) - content=contents.encode('utf-8') - + filename, file_extension = os.path.splitext(fps) print(f"***MMM filename={filename}, extenstion={file_extension}") - + if (file_extension == ".html"): + f=open(fps, "r") + contents =f.read() + f.close() + print("***MMM text file contents =" + str(contents)) + content=contents.encode('utf-8') mime_type=b"text/html" - + elif (file_extension == ".png"): + print("2222222222 binary file read") + f=open(fps,"rb") + ary_bytes=list(f.read()) + contents = "" + #for ele in ary_bytes: + # contents += ele + contents = ''.join([str(elem) for elem in ary_bytes]) + print("***MMM binary file contents =" + str(contents)) + content=contents.encode('utf-8') + f.close() + mime_type=b"image/png" + elif (status_isdir): ary_files = os.listdir(fps) print(f"***MMM list of files in dir {ary_files}") @@ -165,17 +159,10 @@ def response_path(path): print("***MMM file content encoded =" + str(content)) - - # TODO: Fill in the appropriate content and mime_type give the path. + # Done: 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" + return content, mime_type @@ -205,51 +192,55 @@ def server(log_buffer=sys.stderr): if '\r\n\r\n' in request: #print("55555") break - + #print("44444") print("Request received:\n{}\n\n".format(request)) try: - # DONE: Use parse_request to retrieve the path from the request. - path = parse_request(request) - - # DONE: Use response_path to retrieve the content and the mimetype, - # based on the request path. - print("call response_path") - content, mime_type = response_path(path) - - #print("***MMM response content encoded =" + str(content)) - print("***MMM 1111111111111111111111111") - - # 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_AA(content, mime_type) - - print("***MMM ***********************") - #print("88888 response = " + str(response)) + + response = None + if (".ico" in request): + pass + else: + + # DONE: Use parse_request to retrieve the path from the request. + path = parse_request(request) + + # DONE: Use response_path to retrieve the content and the mimetype, + # based on the request path. + print("call response_path") + content, mime_type = response_path(path) + + #print("***MMM response content encoded =" + str(content)) + print("***MMM 1111111111111111111111111") + + + + # DONE: If no exceptions use the content and mimetype from response_path to build a + # response_ok. + response = response_ok(content, mime_type) + + print("***MMM ***********************") + #print("88888 response = " + str(response)) except NameError: + # DONE; If response_path raised + # a NameError, then let response be a not_found response. Else, response = response_not_found() except NotImplementedError: + # Done; If parse_request raised a NotImplementedError, then let + # response be a method_not_allowed response. response = response_method_not_allowed() - - conn.sendall(response) + + if (response is not None): + conn.sendall(response) except: traceback.print_exc() finally: print("***MMM closing connection") conn.close() - + except KeyboardInterrupt: sock.close() return From bb5c65a46ceba4d2369210cb97630df8c0617186 Mon Sep 17 00:00:00 2001 From: mmanc125uw Date: Mon, 14 Sep 2020 09:56:12 -0400 Subject: [PATCH 5/6] sp_py230 lesson3, test runs --- do_integration_tests.bat | 4 +++ do_test_integration.bat | 1 - do_unit_tests.bat | 6 +++++ http_server.py | 52 +++++++++++++++++++++++++++--------- integration_test_results.txt | 16 +++++++++++ tests.py | 30 ++++++++++++--------- unit-tests.py | 26 +++++++++++------- unit_test_results.txt | 23 ++++++++++++++++ 8 files changed, 122 insertions(+), 36 deletions(-) create mode 100644 do_integration_tests.bat delete mode 100644 do_test_integration.bat create mode 100644 do_unit_tests.bat create mode 100644 integration_test_results.txt create mode 100644 unit_test_results.txt diff --git a/do_integration_tests.bat b/do_integration_tests.bat new file mode 100644 index 0000000..01f7e5f --- /dev/null +++ b/do_integration_tests.bat @@ -0,0 +1,4 @@ +python -m unittest -vv tests.py > integration_test_results.txt 2>&1 +type integration_test_results.txt + + diff --git a/do_test_integration.bat b/do_test_integration.bat deleted file mode 100644 index 29e8596..0000000 --- a/do_test_integration.bat +++ /dev/null @@ -1 +0,0 @@ -python -m unittest -vv tests.py diff --git a/do_unit_tests.bat b/do_unit_tests.bat new file mode 100644 index 0000000..23de1c2 --- /dev/null +++ b/do_unit_tests.bat @@ -0,0 +1,6 @@ +python -m unittest -vv unit-tests.py +rem > unit_test_results.txt +rem type unit_test_results.txt + + + diff --git a/http_server.py b/http_server.py index 68d9a0f..1ffd640 100644 --- a/http_server.py +++ b/http_server.py @@ -3,7 +3,7 @@ import traceback import os import mimetypes - +import base64 def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): """ @@ -12,10 +12,6 @@ def response_ok(body=b"This is a minimal response", mimetype=b"text/plain"): # DONE: Implement response_ok - print("***MMM response_ok, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") - #print("***MMM response_ok, response body =" + str(body)) - - return b"\r\n".join([ b"HTTP/1.1 200 OK", b"Content-Type: " + mimetype, @@ -41,7 +37,7 @@ def response_not_found(): # DONE: Implement response_not_found return b"\r\n".join([ - b"HTTP/1.1 404 Method Not Found", + b"HTTP/1.1 404 Not Found", b"", b"You can't do that on this server, 404 error Resource Name Not Found!" ]) @@ -136,18 +132,48 @@ def response_path(path): print("***MMM text file contents =" + str(contents)) content=contents.encode('utf-8') mime_type=b"text/html" + elif (file_extension == ".txt"): + f=open(fps, "r") + contents =f.read() + f.close() + #print("***MMM text file contents =" + str(contents)) + content=contents.encode('utf-8') + mime_type=b"text/plain" elif (file_extension == ".png"): print("2222222222 binary file read") + f=open(fps,"rb") - ary_bytes=list(f.read()) - contents = "" - #for ele in ary_bytes: - # contents += ele - contents = ''.join([str(elem) for elem in ary_bytes]) + #ary_bytes=list(f.read()) + #contents = "" + #contents = ''.join([str(elem) for elem in ary_bytes]) + ary_bytes = f.read() + contents = ary_bytes print("***MMM binary file contents =" + str(contents)) - content=contents.encode('utf-8') - f.close() + #content=contents.encode('utf-8') + content=contents mime_type=b"image/png" + + #contents = base64.b64encode(open(fps, 'rb').read()).decode('utf-8') + #content = contents + #mime_type=b"image/png;base64" + + #f = open(fps, "rb") + #byte = f.read(1) + #while byte: + # print(byte) + # byte = f.read(1) + + + + f.close() + elif (file_extension == ".jpg"): + f=open(fps,"rb") + ary_bytes = f.read() + contents = ary_bytes + #print("***MMM binary file contents =" + str(contents)) + content=contents + mime_type=b"image/jpeg" + f.close() elif (status_isdir): ary_files = os.listdir(fps) diff --git a/integration_test_results.txt b/integration_test_results.txt new file mode 100644 index 0000000..c79bb42 --- /dev/null +++ b/integration_test_results.txt @@ -0,0 +1,16 @@ +test_get_404 (tests.WebTestCase) ... ok +test_get_sample_1_png (tests.WebTestCase) ... ok +test_get_sample_1_png_mime_type (tests.WebTestCase) ... ok +test_get_sample_scene_balls_jpeg (tests.WebTestCase) ... ok +test_get_sample_scene_balls_jpeg_mime_type (tests.WebTestCase) ... ok +test_get_sample_text_content (tests.WebTestCase) ... ok +test_get_sample_text_mime_type (tests.WebTestCase) ... ok +test_images_index (tests.WebTestCase) ... ok +test_ok_response_at_root_index (tests.WebTestCase) ... ok +test_post_yields_method_not_allowed (tests.WebTestCase) ... ok +test_root_index (tests.WebTestCase) ... ok + +---------------------------------------------------------------------- +Ran 11 tests in 11.558s + +OK diff --git a/tests.py b/tests.py index 5315de3..f75da46 100644 --- a/tests.py +++ b/tests.py @@ -35,7 +35,7 @@ def get_response(self, url): return response - def ZZtest_post_yields_method_not_allowed(self): + def test_post_yields_method_not_allowed(self): """ Sending a POST request should yield a 405 Method Not Allowed response """ @@ -50,7 +50,7 @@ def ZZtest_post_yields_method_not_allowed(self): self.assertEqual(response.getcode(), 405) - def xtest_get_sample_text_content(self): + def test_get_sample_text_content(self): """ A call to /sample.txt returns the correct body """ @@ -61,13 +61,19 @@ def xtest_get_sample_text_content(self): error_comment = "Error encountered while visiting " + web_path response = self.get_response(web_path) + sr = response.read() + sr = sr.decode('utf8') + sr = sr.rstrip("\n") self.assertEqual(response.getcode(), 200, error_comment) - with open(local_path, 'rb') as f: - self.assertEqual(f.read(), response.read(), error_comment) + with open(local_path, 'r') as f: + ss = f.read() + ss = ss.rstrip("\n") + self.assertEqual(ss, sr, error_comment) - def xtest_get_sample_text_mime_type(self): + + def test_get_sample_text_mime_type(self): """ A call to /sample.txt returns the correct mimetype """ @@ -81,7 +87,7 @@ def xtest_get_sample_text_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'text/plain', error_comment) - def xtest_get_sample_scene_balls_jpeg(self): + def test_get_sample_scene_balls_jpeg(self): """ A call to /images/Sample_Scene_Balls.jpg returns the correct body """ @@ -98,7 +104,7 @@ def xtest_get_sample_scene_balls_jpeg(self): with open(local_path, 'rb') as f: self.assertEqual(f.read(), response.read(), error_comment) - def xtest_get_sample_scene_balls_jpeg_mime_type(self): + def test_get_sample_scene_balls_jpeg_mime_type(self): """ A call to /images/Sample_Scene_Balls.jpg returns the correct mimetype """ @@ -112,7 +118,7 @@ def xtest_get_sample_scene_balls_jpeg_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'image/jpeg', error_comment) - def xtest_get_sample_1_png(self): + def test_get_sample_1_png(self): """ A call to /images/sample_1.png returns the correct body """ @@ -129,7 +135,7 @@ def xtest_get_sample_1_png(self): with open(local_path, 'rb') as f: self.assertEqual(f.read(), response.read(), error_comment) - def xtest_get_sample_1_png_mime_type(self): + def test_get_sample_1_png_mime_type(self): """ A call to /images/sample_1.png returns the correct mimetype """ @@ -143,7 +149,7 @@ def xtest_get_sample_1_png_mime_type(self): self.assertEqual(response.getcode(), 200, error_comment) self.assertEqual(response.getheader('Content-Type'), 'image/png', error_comment) - def ZZtest_get_404(self): + def test_get_404(self): """ A call to /asdf.txt (a file which does not exist in webroot) yields a 404 error """ @@ -155,7 +161,7 @@ def ZZtest_get_404(self): response = self.get_response(web_path) self.assertEqual(response.getcode(), 404, error_comment) - def ZZtest_images_index(self): + def test_images_index(self): """ A call to /images/ yields a list of files in the images directory """ @@ -187,7 +193,7 @@ def test_root_index(self): for path in os.listdir(local_path): self.assertIn(path, body, error_comment) - def ZZtest_ok_response_at_root_index(self): + def test_ok_response_at_root_index(self): """ A call to / at least yields a 200 OK response """ diff --git a/unit-tests.py b/unit-tests.py index ef3da5c..6ba595f 100644 --- a/unit-tests.py +++ b/unit-tests.py @@ -5,7 +5,7 @@ class TestCase(unittest.TestCase): - def xtest_response_ok(self): + def test_response_ok(self): mimetype = b"image/bmp" body = b"foo" @@ -21,21 +21,21 @@ def xtest_response_ok(self): str_header.splitlines()[0]) self.assertIn("Content-Type: " + mimetype.decode(), str_header) - def xtest_response_method_not_allowed(self): + def test_response_method_not_allowed(self): response = http_server.response_method_not_allowed() str_response = response.decode() self.assertEqual("HTTP/1.1 405 Method Not Allowed", str_response.splitlines()[0]) - def xtest_response_not_found(self): + def test_response_not_found(self): response = http_server.response_not_found() str_response = response.decode() self.assertEqual("HTTP/1.1 404 Not Found", str_response.splitlines()[0]) - def xtest_parse_request_bad_method(self): + def test_parse_request_bad_method(self): request_head = "POST /foo HTTP/1.1" with self.assertRaises(NotImplementedError): @@ -47,17 +47,23 @@ def test_parse_request(self): self.assertEqual(path, http_server.parse_request(request_head)) - def xtest_response_path_file(self): + def test_response_path_file(self): path = "/a_web_page.html" content, mime_type = http_server.response_path(path) + sr = content.decode('utf8') + sr = sr.rstrip("\n") self.assertEqual(b"text/html", mime_type) - with open(os.path.join("webroot", "a_web_page.html"), "rb") as f: - self.assertEqual(f.read(), content) - - def xtest_response_path_dir(self): + with open(os.path.join("webroot", "a_web_page.html"), "r") as f: + ss = f.read() + ss = ss.rstrip("\n") + #print(f" xxxxxx -{sr}-") + #print(f" yyyyyy -{ss}-") + self.assertEqual(sr, ss) + + def test_response_path_dir(self): path = "/" content, mime_type = http_server.response_path(path) @@ -67,7 +73,7 @@ def xtest_response_path_dir(self): self.assertIn(b"sample.txt", content) self.assertIn(b"a_web_page.html", content) - def xtest_response_path_not_found(self): + def test_response_path_not_found(self): path = "/foo/bar/baz/doesnt/exist" with self.assertRaises(NameError): diff --git a/unit_test_results.txt b/unit_test_results.txt new file mode 100644 index 0000000..4b38067 --- /dev/null +++ b/unit_test_results.txt @@ -0,0 +1,23 @@ +***MMM parse_request path= /foo +xxxxxxxxxxxxxxxxxxxxxxx sr = HTTP/1.1 404 Method Not Found + +You can't do that on this server, 404 error Resource Name Not Found! +xxxxxxxxxxxxxxxxxxxxxxx sspl = HTTP/1.1 404 Method Not Found +***MMM response_ok, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +aaa +bbb +response_path fps = webroot\/ +response_path isfile status = False +ccc +response_path isdir status = True +ddd +***MMM list of files in dir ['a_web_page.html', 'favicon.ico', 'images', 'make_time.py', 'sample.txt'] +***MMM file content encoded =b'a_web_page.html\nfavicon.ico\nimages\nmake_time.py\nsample.txt' +aaa +bbb +response_path fps = webroot\/foo/bar/baz/doesnt/exist +response_path isfile status = False +ccc +response_path isdir status = False +ddd +raise nameerror From 5c94120fcee9e250d63fd8a239a5aecef5b615c6 Mon Sep 17 00:00:00 2001 From: mmanc125uw Date: Mon, 14 Sep 2020 11:03:30 -0400 Subject: [PATCH 6/6] sp_py230 lesson3, final refactor, gen results.txt --- do_unit_tests.bat | 5 ++- http_server.py | 67 ++---------------------------------- integration_test_results.txt | 2 +- unit_test_results.txt | 36 +++++++------------ 4 files changed, 18 insertions(+), 92 deletions(-) diff --git a/do_unit_tests.bat b/do_unit_tests.bat index 23de1c2..4d3434b 100644 --- a/do_unit_tests.bat +++ b/do_unit_tests.bat @@ -1,6 +1,5 @@ -python -m unittest -vv unit-tests.py -rem > unit_test_results.txt -rem type unit_test_results.txt +python -m unittest -vv unit-tests.py > unit_test_results.txt 2>&1 +type unit_test_results.txt diff --git a/http_server.py b/http_server.py index 1ffd640..ef40dc2 100644 --- a/http_server.py +++ b/http_server.py @@ -58,7 +58,6 @@ def parse_request(request): if method != "GET": raise NotImplementedError - print("***MMM parse_request path= " + path) return path def response_path(path): @@ -89,107 +88,60 @@ def response_path(path): """ - print("aaa") - content = b"not implemented" mime_type = b"not implemented" - print("bbb") - fps = ('webroot\\' + path) - print("response_path fps = " + str(fps)) - status_isfile = os.path.isfile('webroot\\' + path) - print("response_path isfile status = " + str(status_isfile)) - - print("ccc") - status_isdir = os.path.isdir('webroot\\' + path) - print("response_path isdir status = " + str(status_isdir)) - - print("ddd") # DONE: Raise a NameError if the requested content is not present # under webroot. if ( (status_isfile == False) and (status_isdir == False) ): - print("raise nameerror") raise NameError if (status_isfile): mime_type=b"text/plain" - print("***MMM resource is a file fps =" + fps) - - filename, file_extension = os.path.splitext(fps) - print(f"***MMM filename={filename}, extenstion={file_extension}") - if (file_extension == ".html"): f=open(fps, "r") contents =f.read() f.close() - print("***MMM text file contents =" + str(contents)) content=contents.encode('utf-8') mime_type=b"text/html" elif (file_extension == ".txt"): f=open(fps, "r") contents =f.read() f.close() - #print("***MMM text file contents =" + str(contents)) content=contents.encode('utf-8') mime_type=b"text/plain" elif (file_extension == ".png"): - print("2222222222 binary file read") - f=open(fps,"rb") - #ary_bytes=list(f.read()) - #contents = "" - #contents = ''.join([str(elem) for elem in ary_bytes]) ary_bytes = f.read() contents = ary_bytes - print("***MMM binary file contents =" + str(contents)) - #content=contents.encode('utf-8') content=contents mime_type=b"image/png" - - #contents = base64.b64encode(open(fps, 'rb').read()).decode('utf-8') - #content = contents - #mime_type=b"image/png;base64" - - #f = open(fps, "rb") - #byte = f.read(1) - #while byte: - # print(byte) - # byte = f.read(1) - - - f.close() elif (file_extension == ".jpg"): f=open(fps,"rb") ary_bytes = f.read() contents = ary_bytes - #print("***MMM binary file contents =" + str(contents)) content=contents mime_type=b"image/jpeg" f.close() elif (status_isdir): ary_files = os.listdir(fps) - print(f"***MMM list of files in dir {ary_files}") str_files = '\n'.join(ary_files) content = str_files.encode('utf-8') mime_type=b"text/plain" - - print("***MMM file content encoded =" + str(content)) - # Done: 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 - return content, mime_type @@ -197,7 +149,7 @@ def server(log_buffer=sys.stderr): address = ('127.0.0.1', 10000) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - print("making a server on {0}:{1}".format(*address), file=log_buffer) + #print("making a server on {0}:{1}".format(*address), file=log_buffer) sock.bind(address) sock.listen(1) @@ -210,18 +162,13 @@ def server(log_buffer=sys.stderr): request = '' while True: - #print("11111") data = conn.recv(1024) - #print("22222") request += data.decode('utf8') if '\r\n\r\n' in request: - #print("55555") break - #print("44444") - - print("Request received:\n{}\n\n".format(request)) + #print("Request received:\n{}\n\n".format(request)) try: @@ -235,21 +182,12 @@ def server(log_buffer=sys.stderr): # DONE: Use response_path to retrieve the content and the mimetype, # based on the request path. - print("call response_path") content, mime_type = response_path(path) - #print("***MMM response content encoded =" + str(content)) - print("***MMM 1111111111111111111111111") - - - # DONE: If no exceptions use the content and mimetype from response_path to build a # response_ok. response = response_ok(content, mime_type) - print("***MMM ***********************") - #print("88888 response = " + str(response)) - except NameError: # DONE; If response_path raised # a NameError, then let response be a not_found response. Else, @@ -264,7 +202,6 @@ def server(log_buffer=sys.stderr): except: traceback.print_exc() finally: - print("***MMM closing connection") conn.close() except KeyboardInterrupt: diff --git a/integration_test_results.txt b/integration_test_results.txt index c79bb42..5175ba8 100644 --- a/integration_test_results.txt +++ b/integration_test_results.txt @@ -11,6 +11,6 @@ test_post_yields_method_not_allowed (tests.WebTestCase) ... ok test_root_index (tests.WebTestCase) ... ok ---------------------------------------------------------------------- -Ran 11 tests in 11.558s +Ran 11 tests in 11.688s OK diff --git a/unit_test_results.txt b/unit_test_results.txt index 4b38067..1bcf391 100644 --- a/unit_test_results.txt +++ b/unit_test_results.txt @@ -1,23 +1,13 @@ -***MMM parse_request path= /foo -xxxxxxxxxxxxxxxxxxxxxxx sr = HTTP/1.1 404 Method Not Found - -You can't do that on this server, 404 error Resource Name Not Found! -xxxxxxxxxxxxxxxxxxxxxxx sspl = HTTP/1.1 404 Method Not Found -***MMM response_ok, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -aaa -bbb -response_path fps = webroot\/ -response_path isfile status = False -ccc -response_path isdir status = True -ddd -***MMM list of files in dir ['a_web_page.html', 'favicon.ico', 'images', 'make_time.py', 'sample.txt'] -***MMM file content encoded =b'a_web_page.html\nfavicon.ico\nimages\nmake_time.py\nsample.txt' -aaa -bbb -response_path fps = webroot\/foo/bar/baz/doesnt/exist -response_path isfile status = False -ccc -response_path isdir status = False -ddd -raise nameerror +test_parse_request (unit-tests.TestCase) ... ok +test_parse_request_bad_method (unit-tests.TestCase) ... ok +test_response_method_not_allowed (unit-tests.TestCase) ... ok +test_response_not_found (unit-tests.TestCase) ... ok +test_response_ok (unit-tests.TestCase) ... ok +test_response_path_dir (unit-tests.TestCase) ... ok +test_response_path_file (unit-tests.TestCase) ... ok +test_response_path_not_found (unit-tests.TestCase) ... ok + +---------------------------------------------------------------------- +Ran 8 tests in 0.002s + +OK