mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-03 09:49:31 +02:00
fix: add fallback logic for CDN urls (#1524)
This commit is contained in:
parent
be37402421
commit
3a700f0020
4 changed files with 81 additions and 25 deletions
|
@ -78,6 +78,7 @@ impl CdnUrl {
|
|||
Ok(cdn_url)
|
||||
}
|
||||
|
||||
#[deprecated = "This function only returns the first valid URL. Use try_get_urls instead, which allows for fallback logic."]
|
||||
pub fn try_get_url(&self) -> Result<&str, Error> {
|
||||
if self.urls.is_empty() {
|
||||
return Err(CdnUrlError::Unresolved.into());
|
||||
|
@ -95,6 +96,34 @@ impl CdnUrl {
|
|||
Err(CdnUrlError::Expired.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_get_urls(&self) -> Result<Vec<&str>, Error> {
|
||||
if self.urls.is_empty() {
|
||||
return Err(CdnUrlError::Unresolved.into());
|
||||
}
|
||||
|
||||
let now = Date::now_utc();
|
||||
let urls: Vec<&str> = self
|
||||
.urls
|
||||
.iter()
|
||||
.filter_map(|MaybeExpiringUrl(url, expiry)| match *expiry {
|
||||
Some(expiry) => {
|
||||
if now < expiry {
|
||||
Some(url.as_str())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
None => Some(url.as_str()),
|
||||
})
|
||||
.collect();
|
||||
|
||||
if urls.is_empty() {
|
||||
Err(CdnUrlError::Expired.into())
|
||||
} else {
|
||||
Ok(urls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<CdnUrlMessage> for MaybeExpiringUrls {
|
||||
|
|
|
@ -6,7 +6,6 @@ use std::{
|
|||
use crate::config::{os_version, OS};
|
||||
use crate::{
|
||||
apresolve::SocketAddress,
|
||||
cdn_url::CdnUrl,
|
||||
config::SessionConfig,
|
||||
error::ErrorKind,
|
||||
protocol::{
|
||||
|
@ -27,7 +26,7 @@ use crate::{
|
|||
use bytes::Bytes;
|
||||
use data_encoding::HEXUPPER_PERMISSIVE;
|
||||
use futures_util::future::IntoStream;
|
||||
use http::header::HeaderValue;
|
||||
use http::{header::HeaderValue, Uri};
|
||||
use hyper::{
|
||||
header::{HeaderName, ACCEPT, AUTHORIZATION, CONTENT_TYPE, RANGE},
|
||||
HeaderMap, Method, Request,
|
||||
|
@ -730,16 +729,19 @@ impl SpClient {
|
|||
self.request(&Method::GET, &endpoint, None, None).await
|
||||
}
|
||||
|
||||
pub fn stream_from_cdn(
|
||||
pub fn stream_from_cdn<U>(
|
||||
&self,
|
||||
cdn_url: &CdnUrl,
|
||||
cdn_url: U,
|
||||
offset: usize,
|
||||
length: usize,
|
||||
) -> Result<IntoStream<ResponseFuture>, Error> {
|
||||
let url = cdn_url.try_get_url()?;
|
||||
) -> Result<IntoStream<ResponseFuture>, Error>
|
||||
where
|
||||
U: TryInto<Uri>,
|
||||
<U as TryInto<Uri>>::Error: Into<http::Error>,
|
||||
{
|
||||
let req = Request::builder()
|
||||
.method(&Method::GET)
|
||||
.uri(url)
|
||||
.uri(cdn_url)
|
||||
.header(
|
||||
RANGE,
|
||||
HeaderValue::from_str(&format!("bytes={}-{}", offset, offset + length - 1))?,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue