From 8b13c0762554f567fdd47a52bdcdd39a59d48fbe Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Tue, 27 Aug 2019 14:15:26 +0200 Subject: [PATCH] Fixed #893: empty contentType causing client crash in some Subsonic payloads --- api/funkwhale_api/subsonic/serializers.py | 10 +++++++++- api/tests/subsonic/test_serializers.py | 23 +++++++++++++++++++++++ changes/changelog.d/893.bugfix | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 changes/changelog.d/893.bugfix diff --git a/api/funkwhale_api/subsonic/serializers.py b/api/funkwhale_api/subsonic/serializers.py index 994ad682..85b969b7 100644 --- a/api/funkwhale_api/subsonic/serializers.py +++ b/api/funkwhale_api/subsonic/serializers.py @@ -5,6 +5,7 @@ from rest_framework import serializers from funkwhale_api.history import models as history_models from funkwhale_api.music import models as music_models +from funkwhale_api.music import utils as music_utils def get_artist_data(artist_values): @@ -71,7 +72,14 @@ def get_track_data(album, track, upload): "artist": album.artist.name, "track": track.position or 1, "discNumber": track.disc_number or 1, - "contentType": upload.mimetype, + # Ugly fallback to mp3 but some subsonic clients fail if the value is empty or null, and we don't always + # have the info on legacy uploads + "contentType": upload.mimetype + or ( + music_utils.get_type_from_ext(upload.extension) + if upload.extension + else "audio/mpeg" + ), "suffix": upload.extension or "", "duration": upload.duration or 0, "created": track.creation_date, diff --git a/api/tests/subsonic/test_serializers.py b/api/tests/subsonic/test_serializers.py index 2c468a4f..d6025a90 100644 --- a/api/tests/subsonic/test_serializers.py +++ b/api/tests/subsonic/test_serializers.py @@ -1,3 +1,5 @@ +import pytest + from funkwhale_api.music import models as music_models from funkwhale_api.subsonic import serializers @@ -61,6 +63,27 @@ def test_get_artist_serializer(factories): assert serializers.GetArtistSerializer(artist).data == expected +@pytest.mark.parametrize( + "mimetype, extension, expected", + [ + ("audio/ogg", "noop", "audio/ogg"), + ("", "ogg", "audio/ogg"), + ("", "mp3", "audio/mpeg"), + ("", "", "audio/mpeg"), + ], +) +def test_get_track_data_content_type(mimetype, extension, expected, factories): + upload = factories["music.Upload"]() + upload.mimetype = mimetype + upload.audio_file = "test.{}".format(extension) + + data = serializers.get_track_data( + album=upload.track.album, track=upload.track, upload=upload + ) + + assert data["contentType"] == expected + + def test_get_album_serializer(factories): artist = factories["music.Artist"]() album = factories["music.Album"](artist=artist) diff --git a/changes/changelog.d/893.bugfix b/changes/changelog.d/893.bugfix new file mode 100644 index 00000000..f37ae2a9 --- /dev/null +++ b/changes/changelog.d/893.bugfix @@ -0,0 +1 @@ +Fixed empty contentType causing client crash in some Subsonic payloads (#893) -- GitLab