Create simple threading http server

This commit is contained in:
Иван Солнцев 2023-12-29 02:13:10 +03:00
parent d54b74e65f
commit 6daf9ab0b2
2 changed files with 112 additions and 33 deletions

View file

@ -1,54 +1,128 @@
#!/usr/bin/python3.12 #!/usr/bin/python3.12
import os import threading
import socket import socket
import logging import logging
import config
MAX_REQLINE = 64 * 1024 MAX_REQLINE = 64 * 1024
def service_connections(conn, addr):
recv_file = conn.makefile("rb")
logging.debug("START RECV") class HTTPHandler:
raw = recv_file.readline(MAX_REQLINE + 1) http_type = ""
logging.debug("END RDLINE") http_address = ""
if len(raw) > MAX_REQLINE: headers = {}
logging.debug("Request line is too long") data = b""
return
req_line = raw.decode().rstrip("\r\n") def __init__(self, conn, addr):
self.conn = conn
self.addr = addr
words = req_line.split(" ") self.read_fb = conn.makefile("rb")
self.write_fb = conn.makefile("wb")
if len(words) != 3: self.pre_handle_connection()
logging.debug("Request head too long")
return
if words[0] == "GET": def pre_handle_connection(self):
logging.debug("SEND") raw = self.read_fb.readline(MAX_REQLINE + 1)
conn.send(b"HTTP/1.1 200 OK\r\nServer: cnserv\r\n\r\nNone")
logging.debug("SENDEND")
conn.close()
logging.debug("CONNEND")
if len(raw) > MAX_REQLINE:
logging.debug("Request line too long")
self.conn.send(b"")
self.conn.close()
return
req_line = raw.decode().rstrip("\r\n")
req_line_splited = req_line.split(" ")
if len(req_line_splited) != 3:
logging.debug("Request head too long")
self.conn.send(b"")
self.conn.close()
return
if req_line_splited[2] == "HTTP/1.0" or req_line_splited[2] == "HTTP/1.1":
self.http_type = req_line_splited[0]
self.http_address = req_line_splited[1]
self.http_header_handle()
else:
self.conn.send(b"")
self.conn.close()
def http_header_handle(self):
while True:
raw = self.read_fb.readline(MAX_REQLINE + 1)
if len(raw) > MAX_REQLINE:
logging.debug("Request header line too long")
self.conn.send(b"")
self.conn.close()
return
if raw == b"":
self.conn.send(b"")
self.conn.close()
return
if raw == b"\r\n":
self.http_data_handle()
break
else:
decoded_data = raw.decode("UTF-8").rstrip("\r\n")
decoded_data_split = decoded_data.split(":", 1)
self.headers.update({decoded_data_split[0]: decoded_data_split[1]})
def http_data_handle(self):
# Get from headers Content-Length and get body from request
"""
raw = self.read_fb.readline(1024)
if len(raw) == 1024:
while True:
self.data += raw
if len(raw) < 1024:
break
else:
raw = self.read_fb.readline(1024)
"""
print(self.http_type)
print(self.http_address)
print(self.headers)
print(self.data)
self.send_form_data()
def send_form_data(self):
if self.http_address == "/" and self.http_type == "GET":
self.write_fb.write(b"HTTP/1.1 200 OK\r\nConnection: close\r\nServer: cnserv\r\n\r\nTested!")
self.write_fb.flush()
self.write_fb.close()
self.read_fb.close()
self.conn.close()
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(filename="main.log", filemode="w", encoding="UTF-8", logging.basicConfig(filename="main.log", filemode="a", encoding="UTF-8",
level=logging.DEBUG) level=logging.DEBUG, format="[%(asctime)s][%(levelname)s] %(message)s")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as main_server_socket: logging.info("=== Separator ===")
main_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) try:
main_server_socket.bind(("0.0.0.0", 8080)) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as main_server_socket:
main_server_socket.listen() main_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
main_server_socket.bind(("0.0.0.0", config.SETUP["server"]["port"]))
main_server_socket.listen()
while True: while True:
conn, addr = main_server_socket.accept() conn, addr = main_server_socket.accept()
conn.settimeout(1) logging.info("Accept connection from %s", addr[0])
logging.info("Accept connection from %s", addr[0])
pid = os.fork() thr_serv_conn = threading.Thread(target=HTTPHandler, args=(conn, addr,))
thr_serv_conn.run()
if pid == 0: except KeyboardInterrupt:
service_connections(conn, addr) logging.info("Server get keyboard interrupt. Initialize server to stop")

5
config.py Normal file
View file

@ -0,0 +1,5 @@
SETUP = {
"server": {
"port": 8080,
}
}