summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <tom@vanderlee.io>2022-11-18 13:42:59 +0100
committerGravatar Tom van der Lee <tom@vanderlee.io>2022-11-18 13:42:59 +0100
commitd487ef52521646df62f442d214d62f9ef4696cd0 (patch)
treec0b01ce29a6f823085a0ac8ec437539a9c5687ee
parentf6efa377a68f4997b7b4bdd1bd739c2a29562b31 (diff)
downloadclient-d487ef52521646df62f442d214d62f9ef4696cd0.tar.gz
client-d487ef52521646df62f442d214d62f9ef4696cd0.tar.bz2
client-d487ef52521646df62f442d214d62f9ef4696cd0.zip
Handle client connections gracefully
-rw-r--r--.pre-commit-config.yaml6
-rw-r--r--ttun/client.py51
2 files changed, 34 insertions, 23 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index c5c9a1e..5cecfd3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -6,19 +6,19 @@ repos:
6 - id: end-of-file-fixer 6 - id: end-of-file-fixer
7 - id: trailing-whitespace 7 - id: trailing-whitespace
8 - repo: https://github.com/psf/black 8 - repo: https://github.com/psf/black
9 rev: 21.12b0 9 rev: 22.10.0
10 hooks: 10 hooks:
11 - id: black 11 - id: black
12 types_or: 12 types_or:
13 - python 13 - python
14 - repo: https://github.com/asottile/reorder_python_imports 14 - repo: https://github.com/asottile/reorder_python_imports
15 rev: v2.7.1 15 rev: v3.9.0
16 hooks: 16 hooks:
17 - id: reorder-python-imports 17 - id: reorder-python-imports
18 types_or: 18 types_or:
19 - python 19 - python
20 - repo: https://github.com/pre-commit/mirrors-prettier 20 - repo: https://github.com/pre-commit/mirrors-prettier
21 rev: 'v2.5.1' 21 rev: v2.7.1
22 hooks: 22 hooks:
23 - id: prettier 23 - id: prettier
24 types_or: 24 types_or:
diff --git a/ttun/client.py b/ttun/client.py
index 671ac59..6d05da7 100644
--- a/ttun/client.py
+++ b/ttun/client.py
@@ -11,6 +11,8 @@ from typing import Optional
11from uuid import uuid4 11from uuid import uuid4
12 12
13import websockets 13import websockets
14from aiohttp import ClientConnectionError
15from aiohttp import ClientError
14from aiohttp import ClientSession 16from aiohttp import ClientSession
15from aiohttp import DummyCookieJar 17from aiohttp import DummyCookieJar
16from websockets import WebSocketClientProtocol 18from websockets import WebSocketClientProtocol
@@ -66,14 +68,14 @@ class Client:
66 while True: 68 while True:
67 try: 69 try:
68 request: RequestData = await self.receive() 70 request: RequestData = await self.receive()
69 await self.proxyRequest( 71 await self.proxy_request(
70 request=request, on_response=lambda response: self.send(response) 72 request=request, on_response=lambda response: self.send(response)
71 ) 73 )
72 74
73 except ConnectionClosed: 75 except ConnectionClosed:
74 break 76 break
75 77
76 async def proxyRequest( 78 async def proxy_request(
77 self, 79 self,
78 request: RequestData, 80 request: RequestData,
79 on_response: Callable[[ResponseData], Awaitable] = None, 81 on_response: Callable[[ResponseData], Awaitable] = None,
@@ -92,24 +94,33 @@ class Client:
92 ) 94 )
93 95
94 start = perf_counter() 96 start = perf_counter()
95 response = await session.request( 97 try:
96 method=request["method"], 98 response = await session.request(
97 url=f'http://localhost:{self.port}{request["path"]}', 99 method=request["method"],
98 headers=request["headers"], 100 url=f'http://localhost:{self.port}{request["path"]}',
99 data=b64decode(request["body"].encode()), 101 headers=request["headers"],
100 allow_redirects=False, 102 data=b64decode(request["body"].encode()),
101 ) 103 allow_redirects=False,
102 end = perf_counter() 104 )
103 105 end = perf_counter()
104 response_data = ResponseData( 106
105 status=response.status, 107 response_data = ResponseData(
106 headers=[ 108 status=response.status,
107 (key, value) 109 headers=[
108 for key, value in response.headers.items() 110 (key, value)
109 if key.lower() not in ["transfer-encoding", "content-encoding"] 111 for key, value in response.headers.items()
110 ], 112 if key.lower() not in ["transfer-encoding", "content-encoding"]
111 body=b64encode(await response.read()).decode(), 113 ],
112 ) 114 body=b64encode(await response.read()).decode(),
115 )
116 except ClientError as e:
117 end = perf_counter()
118
119 response_data = ResponseData(
120 status=(504 if isinstance(e, ClientConnectionError) else 502),
121 headers=[("content-type", "text/plain")],
122 body=b64encode(str(e).encode()).decode(),
123 )
113 124
114 if on_response is not None: 125 if on_response is not None:
115 await on_response(response_data) 126 await on_response(response_data)