-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttpserver.py
More file actions
62 lines (51 loc) · 2.23 KB
/
httpserver.py
File metadata and controls
62 lines (51 loc) · 2.23 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
import socket
import threading
from httphandler import HTTPHandler
from posthandler.redirector import POSTHandlerRedirector
from exceptions import UploadedFileTooLarge, MultipartPOSTMissingContentLength
from httpresponse import HTTPResponse
class HTTPServer:
def __init__(self, http_handler=HTTPHandler, max_exchange_mb=500):
self.socket = socket.create_server(('0.0.0.0', 80))
self.httphandler = http_handler
self.max_exchange_bytes = max_exchange_mb * 1_000_000
def start(self):
self.socket.listen()
print('HTTP server up!')
while True:
user_socket, address = self.socket.accept()
threading.Thread(target=self.handle_user, args=(user_socket,)).start()
def handle_user(self, user_socket: socket.socket):
try:
exchange = self.receive_exchange(user_socket)
except UploadedFileTooLarge:
response = HTTPResponse(413).bytes()
except MultipartPOSTMissingContentLength:
response = HTTPResponse(411).bytes()
except ConnectionAbortedError:
user_socket.close()
return False
else:
response = self.httphandler(exchange, posthandler=POSTHandlerRedirector).handle()
user_socket.send(response)
user_socket.close()
return True
def receive_exchange(self, user_socket: socket.socket):
exchange = user_socket.recv(1024)
if len(exchange) == 0:
raise ConnectionAbortedError
http = self.httphandler.http_to_dict(exchange)
if http['method'] == 'POST' and http['Content-Type'].startswith('multipart/form-data'):
if 'Content-Length' not in http.keys():
raise MultipartPOSTMissingContentLength
elif int(http['Content-Length']) > self.max_exchange_bytes:
raise UploadedFileTooLarge
additional_data = b''
received_length = len(http['data'])
while received_length < int(http['Content-Length']):
additional_data += user_socket.recv(4096)
received_length = len(additional_data) + len(http['data'])
exchange += additional_data
return exchange
if __name__ == '__main__':
HTTPServer().start()