-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.py
More file actions
135 lines (90 loc) · 3.37 KB
/
handler.py
File metadata and controls
135 lines (90 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# HTTP handlers implementation
import os
import urllib.parse
import mimetypes
class FileSystemHandler:
"""
A simple HTTP request handler that process GET and HEAD commands.
Serves static files from a directory provided with appropriate MIME type.
"""
def __init__(self, method, path, directory=None, server_version="HttpServer0.1"):
# HTTP Method
self.method = method
#URL Path
self.path = path
# Server version
self.server_version = server_version
# Header list
self.headers = []
# Response buffer
self.response_buffer = ""
# The directory to serve file
if directory is None:
directory = os.getcwd()
self.directory = directory
def handle(self):
"""
Handles a HTTP method.
"""
# Check if a supported HTTP method is requested by the client
# If not raise an exception.
method_function = "process_" + self.method
if not hasattr(self, method_function):
raise Exception("Method not supported")
method = getattr(self, method_function)
method()
return (self.headers, self.response_buffer)
def init_headers(self):
""" Initializes headers for a request """
# Response code and version
self.headers.append("HTTP/1.0 200 OK\r\n")
# Server name
# TODO: Remove the hard coding
self.set_header("Server", self.server_version)
# Content type of the resource
self.set_header("Content-type", mimetypes.guess_type(self.file_path)[0])
def set_header(self, name, value):
""" Set the headers of the response """
self.headers.append("{}: {}\r\n".format(name, value))
def end_header(self):
""" Ends header by appending \r\n at the end of it """
self.headers.append("\r\n")
def process_HEAD(self):
""" Processes HEAD request """
# Get the file path from the request path
self.get_file_path()
# Initialize the headers
self.init_headers()
# Unlike GET, HEAD only needs headers
self.end_header()
def process_GET(self):
""" Processes GET request """
# Get the file path from the request path
self.get_file_path()
# Initializes the headers
self.init_headers()
# Read the file
self.response_buffer = self.read_file()
# Set the content length
self.set_header("Content-length", str(len(self.response_buffer)))
# End the headers
self.end_header()
def get_file_path(self):
""" Returns the absolute file system path of the requested file """
# Discard query parameters and hash URL fragments
file_path = self.path.split("?", 1)[0]
file_path = file_path.split("#", 1)[0]
# Unquote all url characters
file_path = urllib.parse.unquote(file_path)
self.file_path = self.directory + file_path
# If the file is a directory, set the index.html as the file path
if os.path.isdir(self.file_path):
self.file_path += "index.html"
def read_file(self):
""" Reads a file and return its contents """
try:
f = open(self.file_path, "rb")
except Exception as e:
raise e
else:
return f.read()