Compare commits

..

2 commits

Author SHA1 Message Date
Izalia Mae f7e31d9387 add cors headers to api routes 2024-03-30 05:33:26 -04:00
Izalia Mae 587b9483d7 create a task instead of waiting for client posts in workers 2024-03-30 05:33:06 -04:00
7 changed files with 32 additions and 12 deletions

View file

@ -315,11 +315,11 @@ class PushWorker(multiprocessing.Process):
while not self.shutdown.is_set(): while not self.shutdown.is_set():
try: try:
inbox, message, instance = self.queue.get(block=True, timeout=0.25) inbox, message, instance = self.queue.get(block=True, timeout=0.1)
await client.post(inbox, message, instance) asyncio.create_task(client.post(inbox, message, instance))
except Empty: except Empty:
pass await asyncio.sleep(0)
# make sure an exception doesn't bring down the worker # make sure an exception doesn't bring down the worker
except Exception: except Exception:

View file

@ -14,7 +14,7 @@
%link(rel="stylesheet" type="text/css" href="/theme/{{config.theme}}.css" nonce="{{view.request['hash']}}" class="theme") %link(rel="stylesheet" type="text/css" href="/theme/{{config.theme}}.css" nonce="{{view.request['hash']}}" class="theme")
%link(rel="stylesheet" type="text/css" href="/static/style.css" nonce="{{view.request['hash']}}") %link(rel="stylesheet" type="text/css" href="/static/style.css" nonce="{{view.request['hash']}}")
%link(rel="manifest" href="/manifest.json") %link(rel="manifest" href="/manifest.json")
%script(type="application/javascript" src="/static/api.js" nonce="{{view.request['hash']}}", defer) %script(type="application/javascript" src="/static/api.js" nonce="{{view.request['hash']}}" defer)
-block head -block head
%body %body

View file

@ -137,11 +137,13 @@ class HttpClient:
logging.verbose('Failed to parse JSON') logging.verbose('Failed to parse JSON')
return None return None
except ClientSSLError: except ClientSSLError as e:
logging.verbose('SSL error when connecting to %s', urlparse(url).netloc) logging.verbose('SSL error when connecting to %s', urlparse(url).netloc)
logging.warning(str(e))
except (AsyncTimeoutError, ClientConnectionError): except (AsyncTimeoutError, ClientConnectionError) as e:
logging.verbose('Failed to connect to %s', urlparse(url).netloc) logging.verbose('Failed to connect to %s', urlparse(url).netloc)
logging.warning(str(e))
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
@ -210,11 +212,13 @@ class HttpClient:
logging.debug("headers: %s", json.dumps(headers, indent = 4)) logging.debug("headers: %s", json.dumps(headers, indent = 4))
return return
except ClientSSLError: except ClientSSLError as e:
logging.warning('SSL error when pushing to %s', urlparse(url).netloc) logging.warning('SSL error when pushing to %s', urlparse(url).netloc)
logging.warning(str(e))
except (AsyncTimeoutError, ClientConnectionError): except (AsyncTimeoutError, ClientConnectionError) as e:
logging.warning('Failed to connect to %s for message push', urlparse(url).netloc) logging.warning('Failed to connect to %s for message push', urlparse(url).netloc)
logging.warning(str(e))
# prevent workers from being brought down # prevent workers from being brought down
except Exception: except Exception:

View file

@ -116,7 +116,7 @@ class ActorView(View):
return Response.new_error(400, 'actor missing public key', 'json') return Response.new_error(400, 'actor missing public key', 'json')
try: try:
await self.signer.validate_aiohttp_request(self.request) await self.signer.validate_request_async(self.request)
except aputils.SignatureFailureError as e: except aputils.SignatureFailureError as e:
logging.verbose('signature validation failed for "%s": %s', self.actor.id, e) logging.verbose('signature validation failed for "%s": %s', self.actor.id, e)

View file

@ -18,6 +18,12 @@ if typing.TYPE_CHECKING:
from typing import Any from typing import Any
ALLOWED_HEADERS = {
'accept',
'authorization',
'content-type'
}
PUBLIC_API_PATHS: Sequence[tuple[str, str]] = ( PUBLIC_API_PATHS: Sequence[tuple[str, str]] = (
('GET', '/api/v1/relay'), ('GET', '/api/v1/relay'),
('GET', '/api/v1/instance'), ('GET', '/api/v1/instance'),
@ -48,14 +54,20 @@ async def handle_api_path(request: Request, handler: Callable) -> Response:
request['token'] = None request['token'] = None
request['user'] = None request['user'] = None
if check_api_path(request.method, request.path): if request.method != "OPTIONS" and check_api_path(request.method, request.path):
if not request['token']: if not request['token']:
return Response.new_error(401, 'Missing token', 'json') return Response.new_error(401, 'Missing token', 'json')
if not request['user']: if not request['user']:
return Response.new_error(401, 'Invalid token', 'json') return Response.new_error(401, 'Invalid token', 'json')
return await handler(request) response = await handler(request)
if request.path.startswith('/api'):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Headers'] = ', '.join(ALLOWED_HEADERS)
return response
@register_route('/api/v1/token') @register_route('/api/v1/token')

View file

@ -62,6 +62,10 @@ class View(AbstractView):
return await handler(self.request, **self.request.match_info, **kwargs) return await handler(self.request, **self.request.match_info, **kwargs)
async def options(self, request: Request) -> Response:
return Response.new()
@cached_property @cached_property
def allowed_methods(self) -> Sequence[str]: def allowed_methods(self) -> Sequence[str]:
return tuple(self.handlers.keys()) return tuple(self.handlers.keys())

View file

@ -44,7 +44,7 @@ async def handle_frontend_path(request: web.Request, handler: Callable) -> Respo
response = await handler(request) response = await handler(request)
if not request['user'] and request['token']: if not request.path.startswith('/api') and not request['user'] and request['token']:
response.del_cookie('user-token') response.del_cookie('user-token')
return response return response