fix: timeout on spa manifest requests

The previous behaviour had a loop of requests between the front
app and the api when querying the pwa manifest.

This reduce the coupling around the pwa manifest file between the api
and the front app, by uplicating the files so each "service" has a copy
of it, while keeping them in sync and having the front pwa manifest as
single source of truth.

Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2291>
environments/review-docs-2005-xa45z5/deployments/16498
jo 2022-12-17 18:21:41 +01:00
rodzic 6abecfc904
commit b359bb6498
9 zmienionych plików z 151 dodań i 80 usunięć

Wyświetl plik

@ -62,3 +62,13 @@ repos:
rev: v0.8.0.4 rev: v0.8.0.4
hooks: hooks:
- id: shellcheck - id: shellcheck
- repo: local
hooks:
- id: pwa-manifest.json
name: pwa-manifest.json
description: Sync pwa-manifest.json
entry: scripts/sync-pwa-manifest.sh
pass_filenames: false
language: script
files: pwa-manifest.json$

Wyświetl plik

@ -0,0 +1,48 @@
{
"name": "Funkwhale",
"categories": ["music", "entertainment"],
"short_name": "Funkwhale",
"description": "Your free and federated audio platform",
"icons": [
{
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"prefer_related_applications": true,
"related_applications": [
{
"platform": "play",
"url": "https://play.google.com/store/apps/details?id=audio.funkwhale.ffa",
"id": "audio.funkwhale.ffa"
},
{
"platform": "f-droid",
"url": "https://f-droid.org/en/packages/audio.funkwhale.ffa/",
"id": "audio.funkwhale.ffa"
}
],
"shortcuts": [
{
"name": "Search",
"url": "/search",
"icons": []
},
{
"name": "Library",
"url": "/library",
"icons": []
},
{
"name": "Channels",
"url": "/subscriptions",
"icons": []
}
]
}

Wyświetl plik

@ -1,8 +1,8 @@
import json import json
import logging import logging
from pathlib import Path
from cache_memoize import cache_memoize from cache_memoize import cache_memoize
from django.conf import settings
from django.urls import reverse from django.urls import reverse
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
@ -14,7 +14,7 @@ from rest_framework import generics, views
from rest_framework.response import Response from rest_framework.response import Response
from funkwhale_api import __version__ as funkwhale_version from funkwhale_api import __version__ as funkwhale_version
from funkwhale_api.common import middleware, preferences from funkwhale_api.common import preferences
from funkwhale_api.common.renderers import ActivityStreamRenderer from funkwhale_api.common.renderers import ActivityStreamRenderer
from funkwhale_api.federation.actors import get_service_actor from funkwhale_api.federation.actors import get_service_actor
from funkwhale_api.federation.models import Domain from funkwhale_api.federation.models import Domain
@ -118,6 +118,10 @@ class NodeInfo(views.APIView):
) )
PWA_MANIFEST_PATH = Path(__file__).parent / "pwa-manifest.json"
PWA_MANIFEST: dict = json.loads(PWA_MANIFEST_PATH.read_text(encoding="utf-8"))
class SpaManifest(generics.GenericAPIView): class SpaManifest(generics.GenericAPIView):
permission_classes = [] permission_classes = []
authentication_classes = [] authentication_classes = []
@ -126,18 +130,15 @@ class SpaManifest(generics.GenericAPIView):
@extend_schema(operation_id="get_spa_manifest") @extend_schema(operation_id="get_spa_manifest")
def get(self, request): def get(self, request):
existing_manifest = middleware.get_spa_file( manifest = PWA_MANIFEST.copy()
settings.FUNKWHALE_SPA_HTML_ROOT, "manifest.json"
)
parsed_manifest = json.loads(existing_manifest)
instance_name = preferences.get("instance__name") instance_name = preferences.get("instance__name")
if instance_name: if instance_name:
parsed_manifest["short_name"] = instance_name manifest["short_name"] = instance_name
parsed_manifest["name"] = instance_name manifest["name"] = instance_name
instance_description = preferences.get("instance__short_description") instance_description = preferences.get("instance__short_description")
if instance_description: if instance_description:
parsed_manifest["description"] = instance_description manifest["description"] = instance_description
serializer = self.get_serializer(parsed_manifest) serializer = self.get_serializer(manifest)
return Response( return Response(
serializer.data, status=200, content_type="application/manifest+json" serializer.data, status=200, content_type="application/manifest+json"
) )

Wyświetl plik

@ -14,9 +14,10 @@ packages = [
{ include = "config" }, { include = "config" },
] ]
include = [ include = [
{ path = "*.txt" },
{ path = "*.png" },
{ path = "*.html" }, { path = "*.html" },
{ path = "*.json" },
{ path = "*.png" },
{ path = "*.txt" },
] ]
exclude = ["tests"] exclude = ["tests"]

Wyświetl plik

@ -1,4 +1,4 @@
import json from unittest import mock
from django.urls import reverse from django.urls import reverse
@ -38,18 +38,19 @@ def test_admin_settings_correct_permission(db, logged_in_api_client, preferences
assert len(response.data) == len(preferences.all()) assert len(response.data) == len(preferences.all())
def test_manifest_endpoint(api_client, mocker, preferences, tmp_path, settings): def test_manifest_endpoint(api_client, preferences):
settings.FUNKWHALE_SPA_HTML_ROOT = str(tmp_path / "index.html") with mock.patch(
"funkwhale_api.instance.views.PWA_MANIFEST",
{"lang": "unchanged"},
):
preferences["instance__name"] = "Test pod" preferences["instance__name"] = "Test pod"
preferences["instance__short_description"] = "Test description" preferences["instance__short_description"] = "Test description"
base_payload = {}
manifest = tmp_path / "manifest.json"
expected = { expected = {
"lang": "unchanged",
"name": "Test pod", "name": "Test pod",
"short_name": "Test pod", "short_name": "Test pod",
"description": "Test description", "description": "Test description",
} }
manifest.write_bytes(json.dumps(base_payload).encode())
url = reverse("api:v1:instance:spa-manifest") url = reverse("api:v1:instance:spa-manifest")
response = api_client.get(url) response = api_client.get(url)

Wyświetl plik

@ -0,0 +1 @@
Fix timeout on spa manifest requests

Wyświetl plik

@ -0,0 +1,48 @@
{
"name": "Funkwhale",
"categories": ["music", "entertainment"],
"short_name": "Funkwhale",
"description": "Your free and federated audio platform",
"icons": [
{
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"prefer_related_applications": true,
"related_applications": [
{
"platform": "play",
"url": "https://play.google.com/store/apps/details?id=audio.funkwhale.ffa",
"id": "audio.funkwhale.ffa"
},
{
"platform": "f-droid",
"url": "https://f-droid.org/en/packages/audio.funkwhale.ffa/",
"id": "audio.funkwhale.ffa"
}
],
"shortcuts": [
{
"name": "Search",
"url": "/search",
"icons": []
},
{
"name": "Library",
"url": "/library",
"icons": []
},
{
"name": "Channels",
"url": "/subscriptions",
"icons": []
}
]
}

Wyświetl plik

@ -5,6 +5,8 @@ import VueI18n from '@intlify/vite-plugin-vue-i18n'
import { VitePWA } from 'vite-plugin-pwa' import { VitePWA } from 'vite-plugin-pwa'
import { resolve } from 'path' import { resolve } from 'path'
import manifest from './pwa-manifest.json'
const port = +(process.env.VUE_PORT ?? 8080) const port = +(process.env.VUE_PORT ?? 8080)
// https://vitejs.dev/config/ // https://vitejs.dev/config/
@ -35,56 +37,7 @@ export default defineConfig(({ mode }) => ({
type: 'module', type: 'module',
navigateFallback: 'index.html' navigateFallback: 'index.html'
}, },
manifest: { manifest
name: 'Funkwhale',
categories: ['music', 'entertainment'],
start_url: undefined,
scope: undefined,
short_name: 'Funkwhale',
description: 'Your free and federated audio platform',
icons: [
{
src: 'android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png'
}
],
prefer_related_applications: true,
related_applications: [
{
platform: 'play',
url: 'https://play.google.com/store/apps/details?id=audio.funkwhale.ffa',
id: 'audio.funkwhale.ffa'
},
{
platform: 'f-droid',
url: 'https://f-droid.org/en/packages/audio.funkwhale.ffa/',
id: 'audio.funkwhale.ffa'
}
],
shortcuts: [
{
name: 'Search',
url: '/search',
icons: []
},
{
name: 'Library',
url: '/library',
icons: []
},
{
name: 'Channels',
url: '/subscriptions',
icons: []
}
]
}
}) })
], ],
server: { server: {

Wyświetl plik

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -eu
SRC="front/pwa-manifest.json"
DEST="api/funkwhale_api/instance/pwa-manifest.json"
cp "$SRC" "$DEST"