diff options
| author | 2026-09-04 17:09:24 +0200 | |
|---|---|---|
| committer | 2026-09-04 17:09:24 +0200 | |
| commit | 6b6f20a032eb31d747366c8bc270ca81731eaf6a (patch) | |
| tree | ada48080495267bebde4ee1251bbbe77d629745f /ttun_server | |
| parent | 2d22158dd95f76399f5716d556be60c77da04a46 (diff) | |
| download | server-6b6f20a032eb31d747366c8bc270ca81731eaf6a.tar.gz server-6b6f20a032eb31d747366c8bc270ca81731eaf6a.tar.bz2 server-6b6f20a032eb31d747366c8bc270ca81731eaf6a.zip | |
Fixed pre-commit issuesv3
Diffstat (limited to 'ttun_server')
| -rw-r--r-- | ttun_server/__init__.py | 19 | ||||
| -rw-r--r-- | ttun_server/endpoints.py | 2 | ||||
| -rw-r--r-- | ttun_server/redis.py | 4 | ||||
| -rw-r--r-- | ttun_server/types.py | 32 | ||||
| -rw-r--r-- | ttun_server/websockets.py | 60 |
5 files changed, 61 insertions, 56 deletions
diff --git a/ttun_server/__init__.py b/ttun_server/__init__.py index 388dd9e..6e1eabf 100644 --- a/ttun_server/__init__.py +++ b/ttun_server/__init__.py | |||
| @@ -3,7 +3,7 @@ import os | |||
| 3 | 3 | ||
| 4 | from fastapi import FastAPI | 4 | from fastapi import FastAPI |
| 5 | from starlette.middleware.authentication import AuthenticationMiddleware | 5 | from starlette.middleware.authentication import AuthenticationMiddleware |
| 6 | from starlette.routing import Host, Route, WebSocketRoute, Mount | 6 | from starlette.routing import Host, Mount, Route, WebSocketRoute |
| 7 | 7 | ||
| 8 | from authentication.backend import BearerTokenAuthBackend | 8 | from authentication.backend import BearerTokenAuthBackend |
| 9 | from authentication.endpoints import authentication, oauth | 9 | from authentication.endpoints import authentication, oauth |
| @@ -12,20 +12,20 @@ from proxy import app as proxy_app | |||
| 12 | from ttun_server.endpoints import health | 12 | from ttun_server.endpoints import health |
| 13 | from ttun_server.websockets import tunnel | 13 | from ttun_server.websockets import tunnel |
| 14 | 14 | ||
| 15 | logging.basicConfig(level=getattr(logging, os.environ.get('LOG_LEVEL', 'INFO'))) | 15 | logging.basicConfig(level=getattr(logging, os.environ.get("LOG_LEVEL", "INFO"))) |
| 16 | 16 | ||
| 17 | app = FastAPI( | 17 | app = FastAPI( |
| 18 | debug=True, | 18 | debug=True, |
| 19 | routes=[ | 19 | routes=[ |
| 20 | Mount('/management/', app=management), | 20 | Mount("/management/", app=management), |
| 21 | Mount('/auth/', app=authentication), | 21 | Mount("/auth/", app=authentication), |
| 22 | Mount('/oauth/', app=oauth), | 22 | Mount("/oauth/", app=oauth), |
| 23 | WebSocketRoute( | 23 | WebSocketRoute( |
| 24 | '/tunnel/', | 24 | "/tunnel/", |
| 25 | endpoint=tunnel, | 25 | endpoint=tunnel, |
| 26 | ), | 26 | ), |
| 27 | Route('/health/', endpoint=health), | 27 | Route("/health/", endpoint=health), |
| 28 | Host(f'{{subdomain}}.{os.environ['TUNNEL_DOMAIN']}', app=proxy_app) | 28 | Host(f"{{subdomain}}.{os.environ['TUNNEL_DOMAIN']}", app=proxy_app), |
| 29 | ], | 29 | ], |
| 30 | ) | 30 | ) |
| 31 | 31 | ||
| @@ -33,6 +33,7 @@ app.add_middleware(AuthenticationMiddleware, backend=BearerTokenAuthBackend()) | |||
| 33 | 33 | ||
| 34 | try: | 34 | try: |
| 35 | from ._version import version | 35 | from ._version import version |
| 36 | |||
| 36 | __version__ = version | 37 | __version__ = version |
| 37 | except ImportError: | 38 | except ImportError: |
| 38 | __version__ = 'development' | 39 | __version__ = "development" |
diff --git a/ttun_server/endpoints.py b/ttun_server/endpoints.py index 61e3f21..e058009 100644 --- a/ttun_server/endpoints.py +++ b/ttun_server/endpoints.py | |||
| @@ -1,2 +1,2 @@ | |||
| 1 | async def health(): | 1 | async def health(): |
| 2 | return 'OK' | 2 | return "OK" |
diff --git a/ttun_server/redis.py b/ttun_server/redis.py index fb9ff81..dabe940 100644 --- a/ttun_server/redis.py +++ b/ttun_server/redis.py | |||
| @@ -9,5 +9,5 @@ class RedisConnectionPool: | |||
| 9 | @classmethod | 9 | @classmethod |
| 10 | def get_connection(cls) -> Redis: | 10 | def get_connection(cls) -> Redis: |
| 11 | if cls._pool is None: | 11 | if cls._pool is None: |
| 12 | cls._pool = ConnectionPool.from_url(os.environ.get('REDIS_URL')) | 12 | cls._pool = ConnectionPool.from_url(os.environ.get("REDIS_URL")) |
| 13 | return Redis(connection_pool=cls._pool) \ No newline at end of file | 13 | return Redis(connection_pool=cls._pool) |
diff --git a/ttun_server/types.py b/ttun_server/types.py index a0c22a3..33095ff 100644 --- a/ttun_server/types.py +++ b/ttun_server/types.py | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | from asyncio import Queue | 1 | from asyncio import Queue |
| 2 | from enum import Enum | 2 | from enum import Enum |
| 3 | from typing import TypedDict, Optional | 3 | from typing import TypedDict |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | class HttpMessageType(Enum): | 6 | class HttpMessageType(Enum): |
| 7 | request = 'request' | 7 | request = "request" |
| 8 | response = 'response' | 8 | response = "response" |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | class Config(TypedDict): | 11 | class Config(TypedDict): |
| @@ -18,13 +18,13 @@ class HttpRequestData(TypedDict): | |||
| 18 | method: str | 18 | method: str |
| 19 | path: str | 19 | path: str |
| 20 | headers: list[tuple[str, str]] | 20 | headers: list[tuple[str, str]] |
| 21 | body: Optional[str] | 21 | body: str | None |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | class HttpResponseData(TypedDict): | 24 | class HttpResponseData(TypedDict): |
| 25 | status: int | 25 | status: int |
| 26 | headers: list[tuple[str, str]] | 26 | headers: list[tuple[str, str]] |
| 27 | body: Optional[str] | 27 | body: str | None |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | class HttpMessage(TypedDict): | 30 | class HttpMessage(TypedDict): |
| @@ -34,10 +34,10 @@ class HttpMessage(TypedDict): | |||
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | class WebsocketMessageType(Enum): | 36 | class WebsocketMessageType(Enum): |
| 37 | connect = 'connect' | 37 | connect = "connect" |
| 38 | disconnect = 'disconnect' | 38 | disconnect = "disconnect" |
| 39 | message = 'message' | 39 | message = "message" |
| 40 | ack = 'ack' | 40 | ack = "ack" |
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | class WebsocketConnectData(TypedDict): | 43 | class WebsocketConnectData(TypedDict): |
| @@ -50,7 +50,7 @@ class WebsocketDisconnectData(TypedDict): | |||
| 50 | 50 | ||
| 51 | 51 | ||
| 52 | class WebsocketMessageData(TypedDict): | 52 | class WebsocketMessageData(TypedDict): |
| 53 | body: Optional[str] | 53 | body: str | None |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | class WebsocketMessage(TypedDict): | 56 | class WebsocketMessage(TypedDict): |
| @@ -60,13 +60,13 @@ class WebsocketMessage(TypedDict): | |||
| 60 | 60 | ||
| 61 | 61 | ||
| 62 | class MessageType(Enum): | 62 | class MessageType(Enum): |
| 63 | request = 'request' | 63 | request = "request" |
| 64 | response = 'response' | 64 | response = "response" |
| 65 | 65 | ||
| 66 | ws_connect = 'connect' | 66 | ws_connect = "connect" |
| 67 | ws_disconnect = 'disconnect' | 67 | ws_disconnect = "disconnect" |
| 68 | ws_message = 'message' | 68 | ws_message = "message" |
| 69 | ws_ack = 'ack' | 69 | ws_ack = "ack" |
| 70 | 70 | ||
| 71 | 71 | ||
| 72 | Message = HttpMessage | WebsocketMessage | 72 | Message = HttpMessage | WebsocketMessage |
diff --git a/ttun_server/websockets.py b/ttun_server/websockets.py index 88d6cac..a3cbc5f 100644 --- a/ttun_server/websockets.py +++ b/ttun_server/websockets.py | |||
| @@ -16,24 +16,25 @@ from ttun_server.types import ( | |||
| 16 | ) | 16 | ) |
| 17 | 17 | ||
| 18 | logger = logging.getLogger(__name__) | 18 | logger = logging.getLogger(__name__) |
| 19 | logger.setLevel('DEBUG') | 19 | logger.setLevel("DEBUG") |
| 20 | |||
| 20 | 21 | ||
| 21 | async def assert_compatible_version(websocket: WebSocket, config: Config) -> None: | 22 | async def assert_compatible_version(websocket: WebSocket, config: Config) -> None: |
| 22 | client_version = config.get('version', '1.0.0') | 23 | client_version = config.get("version", "1.0.0") |
| 23 | logger.debug('client_version %s', client_version) | 24 | logger.debug("client_version %s", client_version) |
| 24 | 25 | ||
| 25 | if 'git' not in client_version and ttun_server.__version__ != 'development': | 26 | if "git" not in client_version and ttun_server.__version__ != "development": |
| 26 | [client_major, *_] = [int(i) for i in client_version.split('.')[:3]] | 27 | [client_major, *_] = [int(i) for i in client_version.split(".")[:3]] |
| 27 | [server_major, *_] = [int(i) for i in ttun_server.__version__.split('.')] | 28 | [server_major, *_] = [int(i) for i in ttun_server.__version__.split(".")] |
| 28 | 29 | ||
| 29 | if client_major < server_major: | 30 | if client_major < server_major: |
| 30 | await websocket.close(4000, 'Your client is too old') | 31 | await websocket.close(4000, "Your client is too old") |
| 31 | 32 | ||
| 32 | if client_major > server_major: | 33 | if client_major > server_major: |
| 33 | await websocket.close(4001, 'Your client is too new') | 34 | await websocket.close(4001, "Your client is too new") |
| 34 | 35 | ||
| 35 | 36 | ||
| 36 | @requires(['authenticated', 'token'] if conf.ENABLE_AUTH else []) | 37 | @requires(["authenticated", "token"] if conf.ENABLE_AUTH else []) |
| 37 | async def tunnel(websocket: WebSocket) -> None: | 38 | async def tunnel(websocket: WebSocket) -> None: |
| 38 | request_tasks: dict[str, asyncio.Task] = {} | 39 | request_tasks: dict[str, asyncio.Task] = {} |
| 39 | proxy_queues: dict[str, ProxyQueue] = {} | 40 | proxy_queues: dict[str, ProxyQueue] = {} |
| @@ -43,36 +44,39 @@ async def tunnel(websocket: WebSocket) -> None: | |||
| 43 | 44 | ||
| 44 | await assert_compatible_version(websocket, config) | 45 | await assert_compatible_version(websocket, config) |
| 45 | 46 | ||
| 46 | if 'subdomains' not in config: | 47 | if "subdomains" not in config: |
| 47 | config['subdomains'] = [config['subdomain']] | 48 | config["subdomains"] = [config["subdomain"]] |
| 48 | elif config['subdomains'] is None: | 49 | elif config["subdomains"] is None: |
| 49 | config['subdomains'] = [None] | 50 | config["subdomains"] = [None] |
| 50 | 51 | ||
| 51 | for i, subdomain in enumerate(config['subdomains']): | 52 | for i, subdomain in enumerate(config["subdomains"]): |
| 52 | if subdomain is None or await ProxyQueue.has_connection(subdomain): | 53 | if subdomain is None or await ProxyQueue.has_connection(subdomain): |
| 53 | config['subdomains'][i] = uuid4().hex | 54 | config["subdomains"][i] = uuid4().hex |
| 54 | 55 | ||
| 55 | for subdomain in config['subdomains']: | 56 | for subdomain in config["subdomains"]: |
| 56 | proxy_queues[subdomain] = await ProxyQueue.create_for_identifier(subdomain) | 57 | proxy_queues[subdomain] = await ProxyQueue.create_for_identifier(subdomain) |
| 57 | 58 | ||
| 58 | hostname = os.environ.get('TUNNEL_DOMAIN') | 59 | hostname = os.environ.get("TUNNEL_DOMAIN") |
| 59 | protocol = 'https' if os.environ.get('SECURE', False) else 'http' | 60 | protocol = "https" if os.environ.get("SECURE") else "http" |
| 60 | 61 | ||
| 61 | urls = [ | 62 | urls = [ |
| 62 | f'{protocol}://{subdomain}.{hostname}' | 63 | f"{protocol}://{subdomain}.{hostname}" for subdomain in config["subdomains"] |
| 63 | for subdomain in config['subdomains'] | ||
| 64 | ] | 64 | ] |
| 65 | 65 | ||
| 66 | await websocket.send_json({ | 66 | await websocket.send_json( |
| 67 | 'url': urls[0], | 67 | { |
| 68 | 'urls': urls, | 68 | "url": urls[0], |
| 69 | }) | 69 | "urls": urls, |
| 70 | } | ||
| 71 | ) | ||
| 70 | 72 | ||
| 71 | async def handle_requests(subdomain: str) -> None: | 73 | async def handle_requests(subdomain: str) -> None: |
| 72 | while request := await proxy_queues[subdomain].dequeue(): | 74 | while request := await proxy_queues[subdomain].dequeue(): |
| 73 | asyncio.create_task(websocket.send_json(request), name=request['identifier']) | 75 | asyncio.create_task( |
| 76 | websocket.send_json(request), name=request["identifier"] | ||
| 77 | ) | ||
| 74 | 78 | ||
| 75 | for subdomain in config['subdomains']: | 79 | for subdomain in config["subdomains"]: |
| 76 | request_tasks[subdomain] = asyncio.create_task( | 80 | request_tasks[subdomain] = asyncio.create_task( |
| 77 | handle_requests(subdomain), name=subdomain | 81 | handle_requests(subdomain), name=subdomain |
| 78 | ) | 82 | ) |
| @@ -81,8 +85,8 @@ async def tunnel(websocket: WebSocket) -> None: | |||
| 81 | while True: | 85 | while True: |
| 82 | data: Message = await websocket.receive_json() | 86 | data: Message = await websocket.receive_json() |
| 83 | try: | 87 | try: |
| 84 | data['type'] = MessageType(data['type']).value | 88 | data["type"] = MessageType(data["type"]).value |
| 85 | response_queue = await ProxyQueue.get_for_identifier(data['identifier']) | 89 | response_queue = await ProxyQueue.get_for_identifier(data["identifier"]) |
| 86 | await response_queue.enqueue(data) | 90 | await response_queue.enqueue(data) |
| 87 | except AssertionError: | 91 | except AssertionError: |
| 88 | pass | 92 | pass |
