sn-fetch PoC: range probe, weighted planner, parallel segments, reassembly + sha256
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
//! Probing: find out whether a server supports HTTP range requests and
|
||||
//! how large the object is, before planning a segmented download.
|
||||
|
||||
use reqwest::header::{ACCEPT_RANGES, CONTENT_LENGTH};
|
||||
use reqwest::StatusCode;
|
||||
|
||||
use crate::error::FetchError;
|
||||
use crate::types::{FileSize, RangeSupport, TargetUrl};
|
||||
|
||||
/// What a HEAD request (plus fallback range probe) told us about the target.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ProbeInfo {
|
||||
pub range_support: RangeSupport,
|
||||
pub content_length: Option<FileSize>,
|
||||
}
|
||||
|
||||
/// Probe the target: HEAD first; if the `Accept-Ranges` header is absent
|
||||
/// or inconclusive, fall back to a 1-byte GET with a `Range` header and
|
||||
/// check for `206 Partial Content`.
|
||||
pub async fn probe(client: &reqwest::Client, url: &TargetUrl) -> Result<ProbeInfo, FetchError> {
|
||||
let head = client
|
||||
.head(url.inner().clone())
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
|
||||
let content_length = head
|
||||
.headers()
|
||||
.get(CONTENT_LENGTH)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.and_then(|v| v.parse::<u64>().ok());
|
||||
|
||||
let advertised = match head
|
||||
.headers()
|
||||
.get(ACCEPT_RANGES)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.map(str::trim)
|
||||
{
|
||||
Some("bytes") => Some(RangeSupport::Supported),
|
||||
Some("none") => Some(RangeSupport::Unsupported),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let range_support = match advertised {
|
||||
Some(support) => support,
|
||||
// HEAD was inconclusive: ask directly with a 1-byte range.
|
||||
None => {
|
||||
let resp = client
|
||||
.get(url.inner().clone())
|
||||
.header(reqwest::header::RANGE, "bytes=0-0")
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
match resp.status() {
|
||||
StatusCode::PARTIAL_CONTENT => RangeSupport::Supported,
|
||||
StatusCode::OK => RangeSupport::Unsupported,
|
||||
_ => RangeSupport::Unknown,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ProbeInfo {
|
||||
range_support,
|
||||
content_length: content_length.and_then(|len| FileSize::try_new(len).ok()),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user