fixed up and added some things

This commit is contained in:
2026-06-15 23:59:34 +02:00
parent 96eba42c04
commit 095f516a55
4 changed files with 140 additions and 24 deletions
+96 -18
View File
@@ -61,7 +61,7 @@ except ImportError:
)
# pass
AMETHYST_BUILD_NUMBER = "b0.2.0-0072"
AMETHYST_BUILD_NUMBER = "0083"
AMETHYST_REPO = "https://git.novacow.ch/Nova/PyWebServer/"
@@ -111,11 +111,15 @@ class ConfigParser:
def query_config(self, key, host=None):
if host:
return self.data["hosts"].get(host, {}).get(key)
if key == "hosts":
value = self.data["hosts"].get(host, {}).get(key)
elif key == "hosts":
print(f"\n\n\nHosts!\nHosts: {self.data['hosts']}\n\n\n")
return list(self.data["hosts"].keys())
return self.data["globals"].get(key)
value = list(self.data["hosts"].keys())
else:
value = self.data["globals"].get(key)
if value == "0" or value == "1":
value = int(value)
return value
class FileHandler:
@@ -161,7 +165,7 @@ class FileHandler:
if "../" in file_path or "%" in file_path:
return 403
full_path = os.path.join(self.base_dir, file_path.lstrip("/"))
with open(full_path, "a") as f:
with open(full_path, "wb") as f:
f.write(data)
return 0
@@ -186,6 +190,16 @@ class RequestParser:
self.hosts = self.file_handler.read_config("hosts")
print(f"Hosts: {self.hosts}")
def extract_header(self, header: str, request: bytes | str):
if isinstance(request, bytes):
request = request.decode("utf-8", "ignore")
lines = request.splitlines()
for line in lines:
if line.startswith(header):
value = line.split(":")[1][1:]
return value
return None
def parse_request_line(self, line, host):
"""Parses the HTTP request line."""
try:
@@ -263,6 +277,19 @@ class ProxyServer:
def __init__(self, fh):
self.file_handler: FileHandler = fh
@staticmethod
def recv_all(sock):
chunks = []
while True:
try:
data = sock.recv(4096)
if not data:
break
chunks.append(data)
except socket.timeout:
break
return b"".join(chunks)
def try_connection(
self, host: str, port: int, data: bytes, chost: str, force_tls: bool = None
):
@@ -336,10 +363,12 @@ class ProxyServer:
) as ssock:
ssock.sendall(data)
print("data reached")
return ssock.recv(512000)
return self.recv_all(ssock)
else:
raw_sock.sendall(data)
return raw_sock.recv(512000)
resp = self.recv_all(raw_sock)
print(f"resp = {resp}")
return resp
except Exception:
raise
@@ -354,6 +383,7 @@ class WebServer:
self.parser = RequestParser()
self.cert_file = self.file_handler.read_config("cert") or cert_file
self.key_file = self.file_handler.read_config("key") or key_file
self.max_length = int(self.file_handler.read_config("max-length")) or 8192
self.skip_ssl = False
# me when no certificate and key file
@@ -383,8 +413,8 @@ class WebServer:
self.http_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.http_socket.bind(("::", self.http_port))
self.https_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.https_socket.bind(("::", self.https_port))
self.https_socket_raw = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.https_socket_raw.bind(("::", self.https_port))
self.proxy_handler = ProxyServer(self.file_handler)
@@ -395,7 +425,7 @@ class WebServer:
certfile=self.cert_file, keyfile=self.key_file
)
self.https_socket = self.ssl_context.wrap_socket(
self.https_socket, server_side=True
self.https_socket_raw, server_side=True
)
self.http_404_html = (
@@ -430,8 +460,12 @@ class WebServer:
if yn.lower() == "n":
exit(1)
https_thread.start()
else:
self.https_socket.close()
if http is True:
http_thread.start()
else:
self.http_socket.close()
http_thread.join()
https_thread.join()
@@ -464,13 +498,57 @@ class WebServer:
def handle_connection(self, conn, addr):
try:
data = conn.recv(32768)
data = b""
# Read headers
while b"\r\n\r\n" not in data:
chunk = conn.recv(4096)
if not chunk:
break
data += chunk
headers, _, rest = data.partition(b"\r\n\r\n")
# Parse Content-Length
content_length = 0
for line in headers.split(b"\r\n"):
if line.lower().startswith(b"content-length:"):
content_length = int(line.split(b":")[1].strip())
# print(f"Content-Length to server: {content_length}")
# Read body
body = rest
print(f"Rest length: {len(rest)}")
while len(body) < content_length:
chunk = conn.recv(4096)
# print(f"\n\nrecv returned {len(chunk)}\n\n")
if not chunk:
print("\n\nsocket closed\n\n")
break
body += chunk
data += body
#
# print(f"\n\nbody length {len(body)}\n\n")
# print("headers len", len(headers))
# print("rest len", len(rest))
# print("body len", len(body))
# print("content_length", content_length)
#
# print("last 200 bytes of body:")
# print(repr(body[-200:]))
# print("body starts with:")
# print(repr(body[:100]))
# print(f"body: {body}")
print(b"data: " + headers + b"\r\n\r\n" + body)
# # data = conn.recv(32768)
# print(f"len(data) = {len(data)}")
request = data.decode(errors="ignore")
if not data:
response = self.build_response(
400, "Bad Request"
) # user did fucky-wucky
elif len(data) > 8192:
elif len(data) > self.max_length:
response = self.build_response(413, "Request too long")
else:
response = self.handle_request(request, addr)
@@ -493,7 +571,7 @@ class WebServer:
conn.close()
def handle_request(self, data, addr):
print(f"data: {data}")
# print(f"data: {data}")
request_line = data.splitlines()[0]
# Extract host from headers, never works though
@@ -703,11 +781,11 @@ def main():
input("Press <Enter> to continue. ")
file_handler = FileHandler()
file_handler.base_dir = file_handler.read_config("directory")
http_port = file_handler.read_config("port") or 8080
https_port = file_handler.read_config("https-port") or 8443
http_enabled = bool(file_handler.read_config("http")) or True
http_port = file_handler.read_config("port")
https_port = file_handler.read_config("https-port")
http_enabled = bool(file_handler.read_config("http"))
print(http_enabled)
https_enabled = bool(file_handler.read_config("https")) or False
https_enabled = bool(file_handler.read_config("https"))
print(https_enabled)
server = WebServer(http_port=http_port, https_port=https_port)
server.start(http_enabled, https_enabled)