This repository was archived by the owner on Nov 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgens.py
130 lines (92 loc) · 3.06 KB
/
gens.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
import socket
from select import select
from views import index, blog
URLS = {
'/': index,
'/blog': blog
}
tasks = []
to_read = {}
to_write = {}
def server():
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('localhost', 5000))
server_socket.listen(1)
while True:
yield ('read', server_socket)
client_socket, address = server_socket.accept()
print(f'connection from {address}')
tasks.append(client(client_socket))
def client(client_socket):
while True:
yield ('read', client_socket)
request = client_socket.recv(4096)
if not request:
break
else:
response = Response(request)
output = response.generate_response()
yield ('write', client_socket)
client_socket.send(output)
client_socket.close()
def event_loop():
while any([tasks, to_read, to_write]):
while not tasks:
ready_to_read, ready_to_write, _ = select(to_read, to_write, [])
for sock in ready_to_read:
tasks.append(to_read.pop(sock))
for sock in ready_to_write:
tasks.append(to_write.pop(sock))
try:
task = tasks.pop(0)
reason, sock = next(task)
if reason == 'read':
to_read[sock] = task
if reason == 'write':
to_write[sock] = task
except StopIteration:
print('DONE!')
class Response:
request = None
method = None
url = None
METHOD_NOT_ALLOWED = ('HTTP/1.1 405 Method not allowed\n\n', 405)
PAGE_NOT_FOUND = ('HTTP/1.1 404 not found\n\n', 404)
STATUS_OK = ('HTTP/1.1 200 OK\n\n', 200)
def __init__(self, request):
self.request = request
def generate_response(self) -> bytes:
""":returns: encoded bytes"""
self.parse_request()
headers, code = self.validate_request()
body = self.add_mask(code)
return f'{headers} {body}'.encode('utf-8')
def parse_request(self):
"""parse decoded user request"""
parsed = self.request.decode('utf-8').split(' ')
if len(parsed) > 1:
self.method = parsed[0]
self.url = parsed[1]
def validate_request(self) -> tuple:
"""
some toggle validation
:returns: tuple with response
"""
if not self.method == 'GET':
return Response.METHOD_NOT_ALLOWED
if self.url not in URLS:
return Response.PAGE_NOT_FOUND
return Response.STATUS_OK
def add_mask(self, code) -> str:
bad_request = '<h1>{}</h1><p>{}</p>'
if code == 404:
result = bad_request.format(code, 'page not found')
elif code == 405:
result = bad_request.format(code, 'method not allowed')
else:
result = URLS[self.url]()
return result
if __name__ == '__main__':
tasks.append(server())
event_loop()