use std::future::Future;
use std::sync::Arc;
use std::time::Duration;
use reqwest::header::HeaderMap;
const MAX_RANGE_RESPONSE: usize = 16 * 1024 * 1024;
const RANGE_FETCH_TIMEOUT: Duration = Duration::from_secs(30);
pub struct HttpRangeFetcher {
client: Arc<reqwest::Client>,
url: String,
headers: HeaderMap,
}
impl HttpRangeFetcher {
pub fn new(client: Arc<reqwest::Client>, url: impl Into<String>, headers: HeaderMap) -> Self {
Self {
client,
url: url.into(),
headers,
}
}
}
impl media_seek::RangeFetcher for HttpRangeFetcher {
type Error = reqwest::Error;
fn fetch(&self, start: u64, end: u64) -> impl Future<Output = std::result::Result<Vec<u8>, reqwest::Error>> + Send {
let client = Arc::clone(&self.client);
let url = self.url.clone();
let headers = self.headers.clone();
async move {
let response = client
.get(&url)
.headers(headers)
.header("Range", format!("bytes={}-{}", start, end))
.timeout(RANGE_FETCH_TIMEOUT)
.send()
.await?
.error_for_status()?;
let content_length = response.content_length().unwrap_or(0);
if content_length > MAX_RANGE_RESPONSE as u64 {
return Ok(Vec::new());
}
response.bytes().await.map(|b| b.to_vec())
}
}
}