Scille / parsec-cloud

Open source Dropbox-like file sharing with full client encryption !
https://parsec.cloud
Other
268 stars 40 forks source link

[🐛 | Bug]: Organization bootstrap fails #8427

Open Landeers opened 3 days ago

Landeers commented 3 days ago

Parsec version tested on:

v3.0.0-rc.8

Platforms tested on:

Windows

Bug description:

On custom server while bootstrap (join organization with bootstrap link), client received an BootstrapOrganizationErrorInternal error

Relevant output:

Server capture on debug level Capture d’écran 2024-09-18 094414

FirelightFlagboy commented 2 days ago

Look if it's possible to inspect the header value Content-Type

FirelightFlagboy commented 2 days ago

The status 415 correspond to BadContentTypeOrInvalidBodyOrUnknownCommand

https://github.com/Scille/parsec-cloud/blob/1cc43a9656ee3964584f5603174e4c4553be37a3/server/parsec/asgi/rpc.py#L255

FirelightFlagboy commented 2 days ago

It's returned by _handshake_abort_bad_content

That function is call during:

FirelightFlagboy commented 2 days ago

Look if it's possible to inspect the header value Content-Type

I've take a look about how to customize the access log provided by uvicorn

The issue https://github.com/encode/uvicorn/issues/491 was a great help.

I was able to customize uvicorn with a custom access log format (see below)

diff --git a/server/parsec/asgi/__init__.py b/server/parsec/asgi/__init__.py
index 68ba698d3..66f6a2d42 100644
--- a/server/parsec/asgi/__init__.py
+++ b/server/parsec/asgi/__init__.py
@@ -1,6 +1,7 @@
 # Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS
 from __future__ import annotations

+import copy
 from pathlib import Path

 import uvicorn
@@ -8,6 +9,7 @@ from fastapi import FastAPI, Request
 from fastapi.staticfiles import StaticFiles
 from fastapi.templating import Jinja2Templates
 from starlette.types import Receive, Scope, Send
+import uvicorn.config

 from parsec._version import __version__ as parsec_version
 from parsec.asgi.administration import administration_router
@@ -93,6 +95,12 @@ async def serve_parsec_asgi_app(
         v_major, _ = parsec_version.split(".", 1)
         # ex: parsec/3
         server_header = f"parsec/{v_major}"
+    log_config = copy.deepcopy(uvicorn.config.LOGGING_CONFIG)
+    # Eg: "INFO 127.0.0.1 - "GET /anonymous/foobar HTTP/1.1" 200"
+    log_config["formatters"]["access"]["fmt"] = (
+        'foobar %(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s'
+    )
+
     # Note: Uvicorn comes with default values for incoming data size to
     # avoid DoS abuse, so just trust them on that ;-)
     config = uvicorn.Config(
@@ -107,6 +115,7 @@ async def serve_parsec_asgi_app(
         ssl_certfile=ssl_certfile,
         workers=workers,
         # TODO: configure access log format:
+        log_config=log_config,
         # Timestamp is added by the log processor configured in `parsec.logging`,
         # here we configure peer address + req line + rep status + rep body size + time
         # (e.g. "GET 88.0.12.52:54160 /foo 1.1 404 823o 12343ms")

Sadly, The log formatter don't have access to the request scope (HTTPScope) that contains the headers. Where are limited to client_addr, request_line and status_code (see uvicorn/logging.py::AccessFormatter)