-
Notifications
You must be signed in to change notification settings - Fork 0
/
server_lib.py
181 lines (141 loc) · 5.08 KB
/
server_lib.py
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# import necessary modules
import socket, ssl, glob
import json
from database import *
#import os
# Create an empty list for the routes to our webpages
routes = []
class Response():
"""Response object
"""
def __init__(self, status:int, data:str, contentType:str = "text/html", cookies = []):
self.status = status
self.data = data
self.contentType = contentType
def build(self):
"""Builds the HTTP response string
Returns:
string: response string
"""
response = f"HTTP/1.1 {self.status} OK\r\nServer: e-meeuw\r\nContent-type: {self.contentType}; charset=UTF-8\n\r\n\r{self.data}\n\r\n\r"
return response
class Redirect():
"""Redirect object
"""
def __init__(self, webpath:str):
self.webpath = webpath
def build(self):
"""Builds the HTTP response for a redirect
Returns:
string: response string
"""
response = f"HTTP/1.1 301 Moved Permanently\r\nLocation: {self.webpath}\r\nCache-Control: no-store\r\n\r\n"
return response
class Apiroute():
"""Apiroute object
"""
def __init__(self, webpath:str, responseFunc):
self.webpath = webpath
self.responseFunc = responseFunc
self.auth = False
def build(self, request):
"""Connects a function to the api route and passes the request to the function that handles the API
Args:
request (Request): the incomming request
Returns:
Response: An Response object
"""
data = self.responseFunc(request)
data = json.dumps(data)
return Response(200, data, "application/json").build()
class Request():
"""Request object
"""
# Formats a connection request to a string containing the headers
def __init__(self, request:bytes):
self.headers = {}
self.request_string = request.decode()
self.method = self.request_string.split(" ")[0]
self.url = self.request_string.split(" ")[1]
self.body = None
self.cookie = None
# Split the header string and put it in a dictionary object
lines = self.request_string.split('\n',1)[1]
lines = lines.split("\r\n\r\n")
header_lines = lines[0]
try:
self.body = lines[1]
except:
self.body = None
for line in header_lines.split("\r\n"):
words = line.split(":", 1)
self.headers[words[0]] = words[1][1:]
try:
self.cookie = self.headers["Cookie"].split("id=")[1]
except:
pass
def parse_json(self):
"""Parses json in a request
Returns:
Object: the parsed JSON object
"""
# Decode a JSON object to a Python object
try:
return json.loads(self.body)
except:
return {}
class Route():
"""Route object
"""
def __init__(self, webpath:str, localpath:str, contentType:str = "text/html", auth=False):
self.webpath = webpath
self.localpath = localpath
self.contentType = contentType
self.auth = auth
# Build a HTTP response for the route
def build(self, request):
"""Builds a route by finding the file the route is connected to and passing it through the Response.build() method
Args:
request (request): Not used
Returns:
string: the response string
"""
try:
# Try to find the HTML file
file = open(self.localpath).read()
response = Response(200, file, self.contentType).build()
return response
except Exception as e:
print(f"Error: {e}")
# In case we cannot find the HTML file, we send a 404 error
response = Response(404, "Not found").build()
return response
def NewRoute(webpath:str, localpath:str, contentType:str = "text/html", auth:bool = False):
"""Initializes a new route and adds it to the routes array
Args:
webpath (str): the url used in the browser
localpath (str): the path of the file requested
contentType (str, optional): the contenttype of the request/file. Defaults to "text/html".
auth (bool, optional): Can only view this route when you are logged in. Defaults to False.
"""
routes.append(
Route(webpath, localpath, contentType, auth=auth)
)
def FindFiles(folder:str):
"""Finds all files in an folder
Args:
folder (str): the folder you want to find the files in
Returns:
list: a list with files in the folder
"""
files = []
for f in glob.glob(f'./{folder}/**/*.*', recursive=True):
files.append(f)
return files
def FindRoute(routes, url):
# Search the list routes for a route that matches the url of the connection request
for route in routes:
if route.webpath == url:
return route
# If there is no match, we return the route to our error page
return Route("/", "./pages/404.html")