Skip to content

Commit 911ecf8

Browse files
committed
Assignment3 done, test pass
1 parent f7f0dac commit 911ecf8

File tree

1 file changed

+76
-43
lines changed

1 file changed

+76
-43
lines changed

http_server.py

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,74 @@
11
import socket
22
import sys
33
import traceback
4+
import os
5+
import mimetypes
46

57
def 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

2531
def 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

3238
def 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

3945
def 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

5058
def 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

Comments
 (0)