-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
socket servers structure refactoring
- Loading branch information
Showing
5 changed files
with
192 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from lightberry.core.sockets_servers.http.http_socket_server import HttpSocketServer | ||
from lightberry.core.sockets_servers.http.app_server import AppServer | ||
from lightberry.core.sockets_servers.http.ssl_proxy_server import SslProxyServer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from lightberry.config import ServerConfig as Config | ||
from lightberry.core.sockets_servers.http import HttpSocketServer | ||
from lightberry.utils import files_utils | ||
import ssl | ||
import time | ||
import asyncio | ||
|
||
from lightberry.typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: | ||
from asyncio import StreamReader, StreamWriter | ||
from lightberry.core.app import App | ||
|
||
|
||
class AppServer(HttpSocketServer): | ||
def __init__(self, app, host="0.0.0.0", port=Config.SERVER_PORT, debug_mode=Config.DEBUG): | ||
super().__init__(host, port, debug_mode) | ||
|
||
self.ssl_context: ssl.SSLContext | None = None | ||
|
||
self.__app: App = app | ||
self.config = Config | ||
|
||
async def __requests_handler(self, client_r: StreamReader, client_w: StreamWriter): | ||
self.__print_debug(f"connection from: {client_w.get_extra_info('peername')}") | ||
|
||
try: | ||
start_time = time.ticks_ms() if self.debug_mode else None | ||
request = await asyncio.wait_for(self.__load_request(client_r), self.config.TIMEOUT) | ||
|
||
if request: | ||
response = await asyncio.wait_for(self.__app.requests_handler(request), self.__app.config.TIMEOUT) | ||
|
||
if response.is_payload_streamed: | ||
client_w.write(bytes(f"{response.get_headers()}\r\n\r\n", "utf-8")) | ||
await client_w.drain() | ||
|
||
for chunk in response.get_body(): | ||
client_w.write(bytes(chunk, "utf-8")) | ||
await client_w.drain() | ||
else: | ||
client_w.write(bytes(response.get_response_string(), "utf-8")) | ||
await client_w.drain() | ||
|
||
except Exception as e: | ||
self.__print_debug(f"error occurred: {str(e)}", exception=e) | ||
|
||
finally: | ||
client_w.close() | ||
await client_w.wait_closed() | ||
|
||
if self.debug_mode: | ||
self.__print_debug(f"request took: {time.ticks_ms() - start_time}ms") | ||
|
||
def setup(self): | ||
ssl_cert_file = self.config.get("CERT_FILE") | ||
ssl_key_file = self.config.get("CERT_KEY") | ||
|
||
if ((ssl_cert_file and files_utils.file_exists(ssl_cert_file)) and | ||
(ssl_key_file and files_utils.file_exists(ssl_key_file))): | ||
self.ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | ||
self.ssl_context.load_cert_chain(ssl_cert_file, ssl_key_file) | ||
|
||
self.port = 443 | ||
|
||
self.__print_debug("SSL certificate has been loaded...") | ||
|
||
self.server_task = asyncio.start_server(self.__requests_handler, | ||
self.host, | ||
self.port, | ||
ssl=self.ssl_context) |
57 changes: 57 additions & 0 deletions
57
lightberry/core/sockets_servers/http/http_socket_server.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
from lightberry.utils import common_utils | ||
from lightberry.core.communication.request import Request | ||
from lightberry.utils import requests_utils | ||
import asyncio | ||
|
||
from lightberry.typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: | ||
from typing import Type, Coroutine | ||
from lightberry.config.base_config import BaseConfig | ||
from asyncio import StreamReader, StreamWriter | ||
|
||
|
||
class HttpSocketServer: | ||
def __init__(self, | ||
host="0.0.0.0", | ||
port=80, | ||
debug_mode=False): | ||
self.server_task: Coroutine | None = None | ||
|
||
self.debug_mode = debug_mode | ||
self.config: Type[BaseConfig] | None = None | ||
|
||
self.host = host | ||
self.port = port | ||
|
||
async def __load_request(self, request_stream: StreamReader) -> Request | None: | ||
try: | ||
request_header_string = await requests_utils.load_request_header_from_stream(request_stream) | ||
self.__print_debug(f"request header string: {request_header_string}") | ||
|
||
request = Request() | ||
request.parse_header(request_header_string) | ||
|
||
if request.content_length: | ||
request_body_string = await request_stream.readexactly(request.content_length) | ||
request.parse_body(request_body_string.decode()) | ||
|
||
self.__print_debug(f"request body string: {request.body}") | ||
|
||
return request | ||
|
||
except Exception as e: | ||
self.__print_debug(f"error while parsing request", exception=e) | ||
return None | ||
|
||
async def __requests_handler(self, client_r: StreamReader, client_w: StreamWriter): | ||
raise NotImplementedError("Not not implemented") | ||
|
||
def setup(self): | ||
self.server_task = asyncio.start_server(self.__requests_handler, | ||
self.host, | ||
self.port) | ||
|
||
def __print_debug(self, message: str, exception: Exception | None = None): | ||
common_utils.print_debug(message, f"SERVER - {self.__class__.__name__}", | ||
debug_enabled=self.debug_mode, exception=exception) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from lightberry.config import ServerConfig as Config | ||
from lightberry.core.communication.response import Response | ||
from lightberry.core.sockets_servers.http import HttpSocketServer | ||
import asyncio | ||
|
||
from lightberry.typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: | ||
from asyncio import StreamReader, StreamWriter | ||
|
||
|
||
class SslProxyServer(HttpSocketServer): | ||
def __init__(self, wlan, host="0.0.0.0", port=Config.SERVER_PORT, debug_mode=Config.DEBUG): | ||
super().__init__(host, port, debug_mode) | ||
|
||
self.__wlan = wlan | ||
self.hostname = self.__wlan.ifconfig()[0] | ||
self.config = Config | ||
|
||
async def __requests_handler(self, client_r: StreamReader, client_w: StreamWriter): | ||
self.__print_debug(f"connection from: {client_w.get_extra_info('peername')}") | ||
|
||
try: | ||
request = await asyncio.wait_for(self.__load_request(client_r), self.config.TIMEOUT) | ||
|
||
if request: | ||
response = Response(301) | ||
response.add_header("LOCATION", f"https://{self.hostname}{request.url}") | ||
|
||
client_w.write(bytes(response.get_response_string(), "utf-8")) | ||
await client_w.drain() | ||
|
||
except Exception as e: | ||
self.__print_debug(f"error occurred: {str(e)}", exception=e) | ||
|
||
finally: | ||
client_w.close() | ||
await client_w.wait_closed() | ||
|
||
self.__print_debug(f"connection closed") |