wip(sync): use the correct URL for websocket

Co-authored-by: David Larlet <david@larlet.fr>
This commit is contained in:
Yohan Boniface 2025-01-16 16:43:48 +01:00
parent acb2e967b8
commit 36d9e9bf06
5 changed files with 41 additions and 26 deletions

View file

@ -342,6 +342,5 @@ LOGGING = {
WEBSOCKET_ENABLED = env.bool("WEBSOCKET_ENABLED", default=False) WEBSOCKET_ENABLED = env.bool("WEBSOCKET_ENABLED", default=False)
WEBSOCKET_BACK_HOST = env("WEBSOCKET_BACK_HOST", default="localhost") WEBSOCKET_BACK_HOST = env("WEBSOCKET_BACK_HOST", default="localhost")
WEBSOCKET_BACK_PORT = env.int("WEBSOCKET_BACK_PORT", default=8001) WEBSOCKET_BACK_PORT = env.int("WEBSOCKET_BACK_PORT", default=8001)
WEBSOCKET_FRONT_URI = env("WEBSOCKET_FRONT_URI", default="ws://localhost:8001")
REDIS_URL = "redis://localhost:6379" REDIS_URL = "redis://localhost:6379"

View file

@ -76,8 +76,10 @@ export class SyncEngine {
} }
start(authToken) { start(authToken) {
const path = this._umap.urls.get('ws_sync', { map_id: this._umap.id })
const protocol = window.location.protocol === 'http:' ? 'ws:' : 'wss:'
this.transport = new WebSocketTransport( this.transport = new WebSocketTransport(
Utils.template(this._umap.properties.websocketURI, { id: this._umap.id }), `${protocol}//${window.location.host}${path}`,
authToken, authToken,
this this
) )

View file

@ -5,7 +5,7 @@ import uuid
import redis.asyncio as redis import redis.asyncio as redis
from django.conf import settings from django.conf import settings
from django.core.signing import TimestampSigner from django.core.signing import TimestampSigner
from django.urls.resolvers import RoutePattern from django.urls import path
from pydantic import ValidationError from pydantic import ValidationError
from .payloads import ( from .payloads import (
@ -17,20 +17,19 @@ from .payloads import (
Request, Request,
) )
ws_pattern = RoutePattern("/ws/sync/<str:map_id>")
async def application(scope, receive, send): async def application(scope, receive, send):
matched = ws_pattern.match(scope["path"]) path = scope["path"].lstrip("/")
print(matched) for pattern in urlpatterns:
if not matched: if matched := pattern.resolve(path):
print("Wrong path") await matched.func(scope, receive, send, **matched.kwargs)
return break
_, _, kwargs = matched else:
await send({"type": "websocket.close"})
map_id = kwargs["map_id"]
peer = Peer(uuid=uuid.uuid4(), map_id=map_id) async def sync(scope, receive, send, **kwargs):
print(peer) peer = Peer(uuid=uuid.uuid4(), map_id=kwargs["map_id"])
peer._send = send peer._send = send
while True: while True:
event = await receive() event = await receive()
@ -153,3 +152,6 @@ class Peer:
async def send(self, text): async def send(self, text):
print("SEND", text) print("SEND", text)
await self._send({"type": "websocket.send", "text": text}) await self._send({"type": "websocket.send", "text": text})
urlpatterns = [path("ws/sync/<str:map_id>", name="ws_sync", view=sync)]

View file

@ -7,23 +7,36 @@ from django.core.serializers.json import DjangoJSONEncoder
from django.urls import URLPattern, URLResolver, get_resolver from django.urls import URLPattern, URLResolver, get_resolver
def _urls_for_js(urls=None): def _get_url_names(module):
def _get_names(resolver):
names = []
for pattern in resolver.url_patterns:
if getattr(pattern, "url_patterns", None):
# Do not add "admin" and other third party apps urls.
if not pattern.namespace:
names.extend(_get_names(pattern))
elif getattr(pattern, "name", None):
names.append(pattern.name)
return names
return _get_names(get_resolver(module))
def _urls_for_js():
""" """
Return templated URLs prepared for javascript. Return templated URLs prepared for javascript.
""" """
if urls is None: urls = {}
# prevent circular import for module in ["umap.urls", "umap.sync.app"]:
from .urls import i18n_urls, urlpatterns names = _get_url_names(module)
urls.update(
urls = [ dict(zip(names, [get_uri_template(url, module=module) for url in names]))
url.name for url in urlpatterns + i18n_urls if getattr(url, "name", None) )
]
urls = dict(zip(urls, [get_uri_template(url) for url in urls]))
urls.update(getattr(settings, "UMAP_EXTRA_URLS", {})) urls.update(getattr(settings, "UMAP_EXTRA_URLS", {}))
return urls return urls
def get_uri_template(urlname, args=None, prefix=""): def get_uri_template(urlname, args=None, prefix="", module=None):
""" """
Utility function to return an URI Template from a named URL in django Utility function to return an URI Template from a named URL in django
Copied from django-digitalpaper. Copied from django-digitalpaper.
@ -45,7 +58,7 @@ def get_uri_template(urlname, args=None, prefix=""):
paths = template % dict([p, "{%s}" % p] for p in args) paths = template % dict([p, "{%s}" % p] for p in args)
return "%s/%s" % (prefix, paths) return "%s/%s" % (prefix, paths)
resolver = get_resolver(None) resolver = get_resolver(module)
parts = urlname.split(":") parts = urlname.split(":")
if len(parts) > 1 and parts[0] in resolver.namespace_dict: if len(parts) > 1 and parts[0] in resolver.namespace_dict:
namespace = parts[0] namespace = parts[0]

View file

@ -609,7 +609,6 @@ class MapDetailMixin(SessionMixin):
"umap_version": VERSION, "umap_version": VERSION,
"featuresHaveOwner": settings.UMAP_DEFAULT_FEATURES_HAVE_OWNERS, "featuresHaveOwner": settings.UMAP_DEFAULT_FEATURES_HAVE_OWNERS,
"websocketEnabled": settings.WEBSOCKET_ENABLED, "websocketEnabled": settings.WEBSOCKET_ENABLED,
"websocketURI": settings.WEBSOCKET_FRONT_URI,
"importers": settings.UMAP_IMPORTERS, "importers": settings.UMAP_IMPORTERS,
"defaultLabelKeys": settings.UMAP_LABEL_KEYS, "defaultLabelKeys": settings.UMAP_LABEL_KEYS,
} }