From 8ffe4bc1453660c1f211496074ebcc68c924327e Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Mon, 12 Dec 2022 07:22:11 -0700 Subject: A better way of handling URIs between local/remote --- activities/models/post_attachment.py | 18 ++++++++-------- core/uris.py | 34 +++++++++++++++++++++++++++++++ templates/activities/_identity.html | 2 +- templates/activities/_image_uploaded.html | 2 +- templates/activities/_mini_post.html | 2 +- templates/activities/_post.html | 6 +++--- templates/activities/follows.html | 2 +- templates/base.html | 2 +- templates/identity/select.html | 2 +- templates/identity/view.html | 4 ++-- users/models/identity.py | 28 +++++++++++++------------ 11 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 core/uris.py diff --git a/activities/models/post_attachment.py b/activities/models/post_attachment.py index 7b1ad6b..3b1f425 100644 --- a/activities/models/post_attachment.py +++ b/activities/models/post_attachment.py @@ -1,9 +1,9 @@ from functools import partial -from django.conf import settings from django.db import models from core.uploads import upload_namer +from core.uris import AutoAbsoluteUrl, RelativeAbsoluteUrl from stator.models import State, StateField, StateGraph, StatorModel @@ -72,19 +72,19 @@ class PostAttachment(StatorModel): "image/webp", ] - def thumbnail_url(self): + def thumbnail_url(self) -> RelativeAbsoluteUrl: if self.thumbnail: - return self.thumbnail.url + return RelativeAbsoluteUrl(self.thumbnail.url) elif self.file: - return self.file.url + return RelativeAbsoluteUrl(self.file.url) else: - return f"https://{settings.MAIN_DOMAIN}/proxy/post_attachment/{self.pk}/" + return AutoAbsoluteUrl(f"/proxy/post_attachment/{self.pk}/") def full_url(self): if self.file: - return self.file.url + return RelativeAbsoluteUrl(self.file.url) else: - return f"https://{settings.MAIN_DOMAIN}/proxy/post_attachment/{self.pk}/" + return AutoAbsoluteUrl(f"/proxy/post_attachment/{self.pk}/") ### ActivityPub ### @@ -105,8 +105,8 @@ class PostAttachment(StatorModel): return { "id": self.pk, "type": "image" if self.is_image() else "unknown", - "url": self.full_url(), - "preview_url": self.thumbnail_url(), + "url": self.full_url().absolute, + "preview_url": self.thumbnail_url().absolute, "remote_url": None, "meta": { "original": { diff --git a/core/uris.py b/core/uris.py new file mode 100644 index 0000000..9ed2a32 --- /dev/null +++ b/core/uris.py @@ -0,0 +1,34 @@ +from urllib.parse import urljoin + +from django.conf import settings + + +class RelativeAbsoluteUrl: + """ + Represents a URL that can have both "relative" and "absolute" forms + for various use either locally or remotely. + """ + + absolute: str + relative: str + + def __init__(self, absolute: str, relative: str | None = None): + if "://" not in absolute: + raise ValueError(f"Absolute URL {absolute!r} is not absolute!") + self.absolute = absolute + self.relative = relative or absolute + + +class AutoAbsoluteUrl(RelativeAbsoluteUrl): + """ + Automatically makes the absolute variant by using either settings.MAIN_DOMAIN + or a passed identity's URI domain. + """ + + def __init__(self, relative: str, identity=None): + self.relative = relative + if identity: + absolute_prefix = f"https://{identity.domain.uri_domain}/" + else: + absolute_prefix = f"https://{settings.MAIN_DOMAIN}/" + self.absolute = urljoin(absolute_prefix, self.relative) diff --git a/templates/activities/_identity.html b/templates/activities/_identity.html index c48a645..feb3178 100644 --- a/templates/activities/_identity.html +++ b/templates/activities/_identity.html @@ -2,7 +2,7 @@
{{ attachment.name|default:"(no description)" }}
diff --git a/templates/activities/_mini_post.html b/templates/activities/_mini_post.html index 19fad76..9f83333 100644 --- a/templates/activities/_mini_post.html +++ b/templates/activities/_mini_post.html @@ -3,7 +3,7 @@