Subsonic API: now returns 404 when the requested cover art is not found (but a client list has been added to serve them a default cover art)

This commit is contained in:
emeric
2023-11-08 23:43:50 +01:00
parent 475519f19e
commit bd61093898
9 changed files with 188 additions and 162 deletions
@@ -42,6 +42,7 @@ namespace API::Subsonic
ClientInfo clientInfo;
ProtocolVersion serverProtocolVersion;
bool enableOpenSubsonic{ true };
bool enableDefaultCover{ };
};
}
+17 -2
View File
@@ -66,7 +66,7 @@ namespace API::Subsonic
{
std::unordered_map<std::string, ProtocolVersion> res;
Service<IConfig>::get()->visitStrings("api-subsonic-report-old-server-protocol",
Service<IConfig>::get()->visitStrings("api-subsonic-old-server-protocol-clients",
[&](std::string_view client)
{
res.emplace(std::string{ client }, ProtocolVersion{ 1, 12, 0 });
@@ -88,6 +88,19 @@ namespace API::Subsonic
return res;
}
std::unordered_set<std::string> readDefaultCoverClients()
{
std::unordered_set<std::string> res;
Service<IConfig>::get()->visitStrings("api-subsonic-default-cover-clients",
[&](std::string_view client)
{
res.emplace(std::string{ client });
}, { "DSub", "substreamer" });
return res;
}
std::string parameterMapToDebugString(const Wt::Http::ParameterMap& parameterMap)
{
auto censorValue = [](const std::string& type, const std::string& value) -> std::string
@@ -266,6 +279,7 @@ namespace API::Subsonic
SubsonicResource::SubsonicResource(Db& db)
: _serverProtocolVersionsByClient{ readConfigProtocolVersions() }
, _openSubsonicDisabledClients{ readOpenSubsonicDisabledClients() }
, _defaultCoverClients{ readDefaultCoverClients() }
, _db{ db }
{
}
@@ -378,8 +392,9 @@ namespace API::Subsonic
const ClientInfo clientInfo{ getClientInfo(parameters) };
const Database::UserId userId{ authenticateUser(request, clientInfo) };
bool enableOpenSubsonic{ _openSubsonicDisabledClients.find(clientInfo.name) == std::cend(_openSubsonicDisabledClients) };
bool enableDefaultCover{ _defaultCoverClients.find(clientInfo.name) != std::cend(_openSubsonicDisabledClients) };
return { parameters, _db.getTLSSession(), userId, clientInfo, getServerProtocolVersion(clientInfo.name), enableOpenSubsonic };
return { parameters, _db.getTLSSession(), userId, clientInfo, getServerProtocolVersion(clientInfo.name), enableOpenSubsonic, enableDefaultCover };
}
Database::UserId SubsonicResource::authenticateUser(const Wt::Http::Request& request, const ClientInfo& clientInfo)
@@ -53,6 +53,8 @@ namespace API::Subsonic
const std::unordered_map<std::string, ProtocolVersion> _serverProtocolVersionsByClient;
const std::unordered_set<std::string> _openSubsonicDisabledClients;
const std::unordered_set<std::string> _defaultCoverClients;
Database::Db& _db;
};
@@ -207,8 +207,9 @@ namespace API::Subsonic
// Mandatory params
const auto trackId{ getParameterAs<TrackId>(context.parameters, "id") };
const auto releaseId{ getParameterAs<ReleaseId>(context.parameters, "id") };
const auto artistId{ getParameterAs<ArtistId>(context.parameters, "id") };
if (!trackId && !releaseId)
if (!trackId && !releaseId && !artistId)
throw BadParameterGenericError{ "id" };
std::size_t size{ getParameterAs<std::size_t>(context.parameters, "size").value_or(1024) };
@@ -219,6 +220,21 @@ namespace API::Subsonic
cover = Service<Cover::ICoverService>::get()->getFromTrack(*trackId, size);
else if (releaseId)
cover = Service<Cover::ICoverService>::get()->getFromRelease(*releaseId, size);
else if (artistId)
{
// TODO handle a placeholder for artists
response.setStatus(404);
return;
}
if (!cover && context.enableDefaultCover)
cover = Service<Cover::ICoverService>::get()->getDefault(size);
if (!cover)
{
response.setStatus(404);
return;
}
response.out().write(reinterpret_cast<const char*>(cover->getData()), cover->getDataSize());
response.setMimeType(std::string{ cover->getMimeType() });