diff options
| author | UltraQbik <no1skill@yandex.ru> | 2024-08-22 04:45:39 +0300 |
|---|---|---|
| committer | UltraQbik <no1skill@yandex.ru> | 2024-08-22 04:45:39 +0300 |
| commit | 9a539001f3f1e77a6ea8332f659695d7ddcedb2f (patch) | |
| tree | b26ba03bda05a5584f384e18317d380cffcbf178 /main.py | |
| parent | 4f741ce90cd857aba53de06047b9221fa27b0c61 (diff) | |
| download | httpy-9a539001f3f1e77a6ea8332f659695d7ddcedb2f.tar.gz httpy-9a539001f3f1e77a6ea8332f659695d7ddcedb2f.zip | |
Massive refactoring addition of API
Diffstat (limited to 'main.py')
| -rw-r--r-- | main.py | 87 |
1 files changed, 52 insertions, 35 deletions
diff --git a/main.py b/main.py index 25ae922..dc80db6 100644 --- a/main.py +++ b/main.py @@ -5,12 +5,13 @@ The mighty silly webserver written in python for no good reason import ssl import gzip -import time import socket import brotli import signal import asyncio import aiofiles +from src import APIv1 +from src.socks import * from src.request import Request from src.minimizer import minimize_html @@ -40,6 +41,14 @@ PATH_MAP = { "compress": True}, } +# API +API_PATH = { + "/APIv1/file/generated/1gib", + "/APIv1/file/generated/5gib", + "/APIv1/file/generated/10gib", + "/APIv1/file/generated/20gib", +} + # internal path map I_PATH_MAP = { "/err/response.html": {"path": "www/err/response.html"} @@ -122,10 +131,10 @@ class HTTPServer: while True: # try to accept new connection try: - client = (await self._accept(self.socket))[0] + client = (await ssl_sock_accept(self.socket))[0] # if socket was closed -> break - except OSError: + except OSError as e: print("Closed.") break @@ -172,8 +181,6 @@ class HTTPServer: async def handle_get_request(client: ssl.SSLSocket, request: Request): """ Handles user's GET request - :param client: client - :param request: client's request """ # get available compression methods @@ -200,19 +207,47 @@ class HTTPServer: # send 200 response with the file to the client await HTTPServer._send(client, 200, data, headers) - else: - # in case of error, return error page - async with aiofiles.open(I_PATH_MAP["/err/response.html"]["path"], "r") as f: - data = await f.read() - # status code - status_code = 404 + # return after answer + return + + # if it's an API request + elif request.path in API_PATH: + # get API version + api_version = request.path.split("/")[1] + + match api_version: + case "APIv1": + status, data = await APIv1.respond(client, request) + case _: + status = 400 - # format error response - data = data.format(status_code=get_response_code(status_code).decode("ascii")) + # if status is not 200 -> send bad response + if status != 200: + await HTTPServer._bad_response(client, status) - # send 404 response to the client - await HTTPServer._send(client, status_code, data.encode("ascii")) + # return after answer + return + + # in case of error, return error page + await HTTPServer._bad_response(client, 404) + + @staticmethod + async def _bad_response(client: ssl.SSLSocket, status_code: int): + """ + Sends a bad response page to the client. + :param client: client + :param status_code: status code + """ + + async with aiofiles.open(I_PATH_MAP["/err/response.html"]["path"], "r") as f: + data = await f.read() + + # format error response + data = data.format(status_code=get_response_code(status_code).decode("ascii")) + + # send response to the client + await HTTPServer._send(client, status_code, data.encode("ascii")) @staticmethod async def _send(client: ssl.SSLSocket, response: int, data: bytes = None, headers: dict[str, str] = None): @@ -245,7 +280,7 @@ class HTTPServer: byte_header += f"{key}: {value}\r\n".encode("ascii") # send response to the client - await HTTPServer._sendall( + await ssl_sock_sendall( client, b'HTTP/1.1 ' + get_response_code(response) + @@ -276,7 +311,7 @@ class HTTPServer: while True: try: # fetch packet - message = await self._recv(client, self.packet_size) + message = await ssl_sock_recv(client, self.packet_size) except OSError: break @@ -295,24 +330,6 @@ class HTTPServer: # return empty buffer on error return b'' - @staticmethod - async def _accept(sock: ssl.SSLSocket) -> tuple[ssl.SSLSocket, str]: - while True: - try: - return sock.accept() - except BlockingIOError: - time.sleep(1.e-3) - - @staticmethod - async def _recv(sock: ssl.SSLSocket, buflen: int = 1024): - while (msg := sock.recv(buflen)) == b'': - time.sleep(1.e-3) - return msg - - @staticmethod - async def _sendall(sock: ssl.SSLSocket, data: bytes): - sock.sendall(data) - def main(): server = HTTPServer(port=13700) |