11import  socket 
22import  sys 
33import  traceback 
4+ import  os 
5+ import  mimetypes 
46
57def  response_ok (body = b"This is a minimal response" , mimetype = b"text/plain" ):
68    """ 
79    returns a basic HTTP response 
8-     Ex: 
9-         response_ok( 
10-             b"<html><h1>Welcome:</h1></html>", 
11-             b"text/html" 
12-         ) -> 
13- 
14-         b''' 
15-         HTTP/1.1 200 OK\r \n  
16-         Content-Type: text/html\r \n  
17-         \r \n  
18-         <html><h1>Welcome:</h1></html>\r \n  
19-         ''' 
10+          Ex: 
11+              response_ok( 
12+                  b"<html><h1>Welcome:</h1></html>", 
13+                  b"text/html" 
14+              ) -> 
15+ 
16+              b''' 
17+              HTTP/1.1 200 OK\r \n  
18+              Content-Type: text/html\r \n  
19+              \r \n  
20+              <html><h1>Welcome:</h1></html>\r \n  
21+              ''' 
2022    """ 
2123
2224    # TODO: Implement response_ok 
23-     return  b"" 
25+     return  b"\r \n " .join ([
26+         b"HTTP/1.1 200 OK" ,
27+         b"Content-Type: "  +  mimetype ,
28+         b"" ,body 
29+         ])
2430
2531def  response_method_not_allowed ():
2632    """Returns a 405 Method Not Allowed response""" 
2733
2834    # TODO: Implement response_method_not_allowed 
29-     return  b""  
35+     return  b"\r \n "  . join ([ b"HTTP/1.1 405 Method Not Allowed" ]) 
3036
3137
3238def  response_not_found ():
3339    """Returns a 404 Not Found response""" 
3440
3541    # TODO: Implement response_not_found 
36-     return  b""  
42+     return  b"\r \n "  . join ([ b"HTTP/1.1 404 Not Found" ]) 
3743
3844
3945def  parse_request (request ):
4046    """ 
4147    Given the content of an HTTP request, returns the path of that request. 
4248
43-     This server only handles GET requests, so this method shall raise a 
44-     NotImplementedError if the method of the request is not GET. 
49+          This server only handles GET requests, so this method shall raise a 
50+          NotImplementedError if the method of the request is not GET. 
4551    """ 
46- 
52+     method , path , version  =  request .split ("\r \n " )[0 ].split (" " )
53+     if  method  !=  "GET" :
54+         raise  NotImplementedError 
4755    # TODO: implement parse_request 
48-     return  "" 
56+     return  path 
4957
5058def  response_path (path ):
5159    """ 
5260    This method should return appropriate content and a mime type. 
5361
54-     If the requested path is a directory, then the content should be a 
55-     plain-text listing of the contents with mimetype `text/plain`. 
62+          If the requested path is a directory, then the content should be a 
63+          plain-text listing of the contents with mimetype `text/plain`. 
5664
57-     If the path is a file, it should return the contents of that file 
58-     and its correct mimetype. 
65+          If the path is a file, it should return the contents of that file 
66+          and its correct mimetype. 
5967
60-     If the path does not map to a real location, it should raise an 
61-     exception that the server can catch to return a 404 response. 
68+          If the path does not map to a real location, it should raise an 
69+          exception that the server can catch to return a 404 response. 
6270
63-     Ex: 
71+          Ex: 
6472        response_path('/a_web_page.html') -> (b"<html><h1>North Carolina...", 
6573                                            b"text/html") 
6674
@@ -85,9 +93,27 @@ def response_path(path):
8593    # If the path is "make_time.py", then you may OPTIONALLY return the 
8694    # result of executing `make_time.py`. But you need only return the 
8795    # CONTENTS of `make_time.py`. 
88-     
89-     content  =  b"not implemented" 
90-     mime_type  =  b"not implemented" 
96+ 
97+ 
98+ 
99+     file_path  =  os .path .join (os .getcwd (), 'webroot' , path .strip ('/' ))
100+ 
101+     # If the path indicates a directory: 
102+     if  os .path .isdir (file_path ):
103+         content  =  "\n " .join (os .listdir (file_path )).encode ('utf8' )
104+         mime_type  =  b"text/plain" 
105+         return  content , mime_type 
106+ 
107+     # If the path indicates a file: 
108+     elif  os .path .exists (file_path ):
109+         mime_type  =  mimetypes .guess_type (file_path )[0 ].encode ('utf8' )
110+         with  open (file_path , "br" ) as  f :
111+             content  =  f .read ()
112+         return  content , mime_type 
113+ 
114+     # If the path does not indicate an existing directory or file: 
115+     else :
116+         raise  NameError 
91117
92118    return  content , mime_type 
93119
@@ -114,30 +140,37 @@ def server(log_buffer=sys.stderr):
114140
115141                    if  '\r \n \r \n '  in  request :
116142                        break 
117- 		 
143+ 
118144
119145                print ("Request received:\n {}\n \n " .format (request ))
146+                 try :
147+                     path  =  parse_request (request )
148+ 
149+                     # TODO: Use parse_request to retrieve the path from the request. 
120150
121-                 # TODO: Use parse_request to retrieve the path from the request. 
151+                     # TODO: Use response_path to retrieve the content and the mimetype, 
152+                     # based on the request path. 
122153
123-                 # TODO: Use response_path to retrieve the content and the mimetype, 
124-                 # based on the request path. 
154+                     # TODO; If parse_request raised a NotImplementedError, then let 
155+                     # response be a method_not_allowed response. If response_path raised 
156+                     # a NameError, then let response be a not_found response. Else, 
157+                     # use the content and mimetype from response_path to build a 
158+                     # response_ok. 
159+                     content , mimetype  =  response_path (path )
160+                 except  NotImplementedError :
161+                     response  =  response_method_not_allowed ()
162+                     conn .sendall (response )
163+                 except  NameError :
164+                     response  =  response_not_found ()
165+                     conn .sendall (response )
125166
126-                 # TODO; If parse_request raised a NotImplementedError, then let 
127-                 # response be a method_not_allowed response. If response_path raised 
128-                 # a NameError, then let response be a not_found response. Else, 
129-                 # use the content and mimetype from response_path to build a  
130-                 # response_ok. 
131-                 response  =  response_ok (
132-                     body = b"Welcome to my web server" ,
133-                     mimetype = b"text/plain" 
134-                 )
167+                 response  =  response_ok (content , mimetype )
135168
136169                conn .sendall (response )
137170            except :
138171                traceback .print_exc ()
139172            finally :
140-                 conn .close ()  
173+                 conn .close ()
141174
142175    except  KeyboardInterrupt :
143176        sock .close ()
0 commit comments