chore: initial sanitized public snapshot
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
use super::{
|
||||
Downloader, FtpConfigModel, FtpRequestModel, FtpResponseModel, HttpConnector, HttpRequestModel,
|
||||
HttpResponseModel, HttpTransferTaskModel, HttpsConnector, SftpConfigModel, SftpRequestModel,
|
||||
SftpResponseModel, TransportError,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
/// Placeholder HTTP connector that always reports that no connector is configured.
|
||||
pub struct NullHttpConnector;
|
||||
|
||||
impl HttpConnector for NullHttpConnector {
|
||||
fn connect_http(
|
||||
&self,
|
||||
request: &HttpRequestModel,
|
||||
) -> Result<HttpResponseModel, TransportError> {
|
||||
Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::NotConnected,
|
||||
message: format!("no http connector configured for {}", request.url),
|
||||
source: None,
|
||||
context: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
/// Placeholder HTTPS connector that always reports that no connector is configured.
|
||||
pub struct NullHttpsConnector;
|
||||
|
||||
impl HttpsConnector for NullHttpsConnector {
|
||||
fn connect_https(
|
||||
&self,
|
||||
request: &HttpRequestModel,
|
||||
) -> Result<HttpResponseModel, TransportError> {
|
||||
Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::NotConnected,
|
||||
message: format!("no https connector configured for {}", request.url),
|
||||
source: None,
|
||||
context: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
/// Downloader wrapper that routes HTTP and HTTPS requests through connector implementations.
|
||||
pub struct ConnectorBackedDownloader<HC, HSC> {
|
||||
/// Connector used for plain HTTP requests.
|
||||
http: HC,
|
||||
/// Connector used for HTTPS requests.
|
||||
https: HSC,
|
||||
}
|
||||
|
||||
impl<HC, HSC> ConnectorBackedDownloader<HC, HSC> {
|
||||
#[must_use]
|
||||
/// Builds a downloader from plain HTTP and HTTPS connector implementations.
|
||||
pub const fn new(http: HC, https: HSC) -> Self {
|
||||
Self { http, https }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
/// Downloader that only supports HTTP(S) transfers.
|
||||
pub struct HttpOnlyDownloader {
|
||||
/// Connector-backed executor used by the HTTP-only wrapper.
|
||||
inner: ConnectorBackedDownloader<NullHttpConnector, NullHttpsConnector>,
|
||||
}
|
||||
|
||||
impl HttpOnlyDownloader {
|
||||
#[must_use]
|
||||
/// Builds the HTTP-only downloader.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: ConnectorBackedDownloader::new(NullHttpConnector, NullHttpsConnector),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Downloader for HttpOnlyDownloader {
|
||||
fn start_http_transfer(
|
||||
&self,
|
||||
task: &HttpTransferTaskModel,
|
||||
) -> Result<HttpResponseModel, TransportError> {
|
||||
self.inner.start_http_transfer(task)
|
||||
}
|
||||
|
||||
fn start_ftp_transfer(
|
||||
&self,
|
||||
_config: &FtpConfigModel,
|
||||
_request: &FtpRequestModel,
|
||||
) -> Result<FtpResponseModel, TransportError> {
|
||||
Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::UnsupportedScheme,
|
||||
message: "ftp transfer is not supported by the HTTP-only downloader".to_owned(),
|
||||
source: None,
|
||||
context: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn start_sftp_transfer(
|
||||
&self,
|
||||
_config: &SftpConfigModel,
|
||||
_request: &SftpRequestModel,
|
||||
) -> Result<SftpResponseModel, TransportError> {
|
||||
Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::UnsupportedScheme,
|
||||
message: "sftp transfer is not supported by the HTTP-only downloader".to_owned(),
|
||||
source: None,
|
||||
context: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<HC, HSC> Downloader for ConnectorBackedDownloader<HC, HSC>
|
||||
where
|
||||
HC: HttpConnector,
|
||||
HSC: HttpsConnector,
|
||||
{
|
||||
fn start_http_transfer(
|
||||
&self,
|
||||
task: &HttpTransferTaskModel,
|
||||
) -> Result<HttpResponseModel, TransportError> {
|
||||
match request_scheme(&task.request.url) {
|
||||
Some("http") => self
|
||||
.http
|
||||
.connect_http(&task.request)
|
||||
.map(|response| normalize_http_response_for_execution(task, response)),
|
||||
Some("https") => self
|
||||
.https
|
||||
.connect_https(&task.request)
|
||||
.map(|response| normalize_http_response_for_execution(task, response)),
|
||||
Some(scheme) => Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::UnsupportedScheme,
|
||||
message: format!("unsupported http transfer scheme: {scheme}"),
|
||||
source: None,
|
||||
context: None,
|
||||
}),
|
||||
None => Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::ProtocolViolation,
|
||||
message: format!("request url has no scheme: {}", task.request.url),
|
||||
source: None,
|
||||
context: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn start_ftp_transfer(
|
||||
&self,
|
||||
_config: &FtpConfigModel,
|
||||
_request: &FtpRequestModel,
|
||||
) -> Result<FtpResponseModel, TransportError> {
|
||||
Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::UnsupportedScheme,
|
||||
message: "ftp transfer is not implemented".to_owned(),
|
||||
source: None,
|
||||
context: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn start_sftp_transfer(
|
||||
&self,
|
||||
_config: &SftpConfigModel,
|
||||
_request: &SftpRequestModel,
|
||||
) -> Result<SftpResponseModel, TransportError> {
|
||||
Err(TransportError {
|
||||
kind: crate::transport::TransportErrorKind::UnsupportedScheme,
|
||||
message: "sftp transfer is not implemented".to_owned(),
|
||||
source: None,
|
||||
context: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Injects transfer-task metadata such as checksum hooks into one HTTP response model.
|
||||
pub(super) fn normalize_http_response_for_execution(
|
||||
task: &HttpTransferTaskModel,
|
||||
mut response: HttpResponseModel,
|
||||
) -> HttpResponseModel {
|
||||
if response.checksum.is_none()
|
||||
&& let Some(checksum) = task
|
||||
.checksum_hook
|
||||
.as_ref()
|
||||
.filter(|checksum| checksum.enabled)
|
||||
.map(|checksum| checksum.spec.clone())
|
||||
{
|
||||
response.checksum = Some(checksum);
|
||||
}
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
/// Extracts the lowercase URI scheme prefix from one request URL when present.
|
||||
pub(super) fn request_scheme(url: &str) -> Option<&str> {
|
||||
url.split_once("://").map(|(scheme, _)| scheme)
|
||||
}
|
||||
Reference in New Issue
Block a user