use std::process::Command;
use std::sync::{Arc, atomic::AtomicBool};
use std::thread::JoinHandle;
use crate::{
DownloadResult, DownloadSink, ResponseError, StartError,
drivers::{Driver, Request},
util,
};
#[derive(Debug, Clone, Copy)]
pub(crate) struct CurlDriver;
impl Driver for CurlDriver {
fn start(
&self,
req: Request,
sink: DownloadSink,
cancel: Arc<AtomicBool>,
) -> Result<JoinHandle<Result<DownloadResult, ResponseError>>, StartError> {
let mut cmd = Command::new("curl");
cmd.arg("-sS")
.arg("--compressed")
.arg("-o")
.arg("-")
.arg("-w")
.arg("%{stderr}%{http_code}")
.arg(req.url.to_url_string());
if req.follow_redirects {
cmd.arg("-L");
}
for (k, v) in util::add_common_headers(&req) {
cmd.arg("-H").arg(format!("{k}: {v}"));
}
util::spawn_download_cmd_thread(cmd, "curl", req, sink, cancel, download_curl)
}
}
fn download_curl(
output: std::process::Output,
_req: &Request,
) -> Result<(u16, Option<crate::ContentEncoding>), ResponseError> {
let code_str = String::from_utf8_lossy(&output.stderr).trim().to_string();
let code: u16 = code_str
.parse()
.map_err(|_| ResponseError::BadStatusCode(code_str))?;
Ok((code, None))
}