Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 85 additions & 6 deletions resources/session02/homework/http_server.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,62 @@
#!/usr/bin/env python3

"""
FAILED (failures=8, errors=4)
FAILED (failures=10)
Homework
Take the following steps one at a time. Run the tests in
assignments/session02/homework between to ensure that you are getting it
right.

1) Complete the stub resolve_uri function so that it handles looking up
resources on disk using the URI returned by parse_request.

2) Make sure that if the URI does not map to a file that exists, it raises
an appropriate error for our server to handle.

3) Complete the response_not_found function stub so that it returns a 404
response.

4) Update response_ok so that it uses the values returned by resolve_uri by
the URI. (these have already been added to the function signature)
You'll plug those values into the response you generate in the way
required by the protocol

@maria:

When starting the homework, start by first getting just this test to pass:
```python tests.py ResolveURITestCase.test_directory_resource```

You might find the test to look confusing at first. It is testing the
function resolve_uri (the function above this test assigns
call_function_under_test to this function).

It is expecting that this function is going to return two objects,

Look at the test to figure out what these objects should be.

python tests.py ResolveURITestCase.test_directory_resource

python tests.py ResponseOkTestCase.test_passed_mimetype_in_response
"""

import socket
import sys
import os
import mimetypes


def response_ok(body=b"this is a pretty minimal response", mimetype=b"text/plain"):
"""returns a basic HTTP response"""
resp = []
resp.append(b"HTTP/1.1 200 OK")
resp.append(b"Content-Type: text/plain")
# resp.append(b"Content-Type: text/plain")
resp.append(b"Content-Type: " + mimetype)
resp.append(b"")
resp.append(b"this is a pretty minimal response")
return b"\r\n".join(resp)
resp.append(body)
# resp.append(b"this is a pretty minimal response")

return b"\r\n".join(resp)

def response_method_not_allowed():
"""returns a 405 Method Not Allowed response"""
Expand All @@ -22,7 +68,11 @@ def response_method_not_allowed():

def response_not_found():
"""returns a 404 Not Found response"""
return b""
# return b""
resp = []
resp.append("HTTP/1.1 404 Not Found")
resp.append("")
return "\r\n".join(resp).encode('utf8')


def parse_request(request):
Expand All @@ -32,10 +82,39 @@ def parse_request(request):
raise NotImplementedError("We only accept GET")
return uri


def resolve_uri(uri):
"""This method should return appropriate content and a mime type"""
return b"still broken", b"text/plain"
"""Your resolve_uri function will need to accomplish the following tasks:

It should take a URI as the sole argument
It should map the pathname represented by the URI to a filesystem location.
It should have a 'home directory', and look only in that location.
If the URI is a directory, it should return a plain-text listing of the
directory contents and the mimetype text/plain.
If the URI is a file, it should return the contents of that file and its
correct mimetype.
If the URI does not map to a real location, it should raise an exception
that the server can catch to return a 404 response.
"""
# print("URI: {}".format(uri))
webroot = "/webroot"
path = os.getcwd() + webroot + uri
# content = b"" # Adding this fails additional test
mimetype = b"text/plain"
try:
if os.path.isfile(path):
with open(path, "rb") as f:
content = f.read()
mimetype = mimetypes.guess_type(path)[0].encode('utf-8')
if os.path.isdir(path):
content = os.listdir(path)
content = ';'.join(content)
content = content.encode("utf-8")
except:
# raise NameError("File not found")
return response_not_found()
# return b"still broken", b"text/plain"
return content, mimetype


def server(log_buffer=sys.stderr):
Expand Down
43 changes: 35 additions & 8 deletions resources/session02/http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ def server(log_buffer=sys.stderr):
conn, addr = sock.accept() # blocking
try:
print('connection - {0}:{1}'.format(*addr), file=log_buffer)
request = ""
while True:
data = conn.recv(16)
print('received "{0}"'.format(data), file=log_buffer)
if data:
print('sending data back to client', file=log_buffer)
conn.sendall(data)
else:
msg = 'no more data from {0}:{1}'.format(*addr)
print(msg, log_buffer)
data = conn.recv(1024)
request += data.decode('utf8')
if len(data) < 1024:
break
print('sending response', file=log_buffer)
response = response_ok()
conn.sendall(response)
finally:
conn.close()

Expand All @@ -34,6 +33,34 @@ def server(log_buffer=sys.stderr):
return


def response_ok():
"""this function returns the simple http response"""

resp = []
resp.append(b"HTTP/1.1 200 OK")
resp.append(b"Content-Type: text/plain")
resp.append(b"")
resp.append(b"this is a pretty minimal response")

return b"\r\n".join(resp)


def parse_request(request):
first_line = request.split("\r\n")[0]
method, uri, protocol = first_line.split()
if method != "GET":
raise NotImplementedError("We only accept GET")
print('request is okay', file=sys.stderr)


def response_method_not_allowed():
"""returns a 405 Method Not Allowed response"""
resp = []
resp.append(b"HTTP/1.1 405 Method Not Allowed")
resp.append(b"")
return b"\r\n".join(resp)


if __name__ == '__main__':
server()
sys.exit(0)