diff --git a/Cargo.toml b/Cargo.toml index cb3524b..dbcfab5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ name = "partialzip" readme = "README.md" repository = "https://github.com/marcograss/partialzip" rust-version = "1.60.0" -version = "1.2.5-alpha.1" +version = "1.2.6" [dependencies] anyhow = "1.0.66" diff --git a/src/bin/partialzip.rs b/src/bin/partialzip.rs index 810e80e..2ad8fca 100644 --- a/src/bin/partialzip.rs +++ b/src/bin/partialzip.rs @@ -10,7 +10,7 @@ use url::Url; /// Handler to list the files from command line fn list(url: &str, files_only: bool, must_ranged: bool) -> Result<()> { let url = Url::parse(url)?; - let mut pz = PartialZip::new(&url, must_ranged)?; + let mut pz = PartialZip::new_check_range(&url, must_ranged)?; let l = pz.list(); for f in l { let descr = if files_only { @@ -34,7 +34,7 @@ fn download(url: &str, filename: &str, outputfile: &str, must_ranged: bool) -> R return Err(anyhow!("The output file {outputfile} already exists")); } let url = Url::parse(url)?; - let mut pz = PartialZip::new(&url, must_ranged)?; + let mut pz = PartialZip::new_check_range(&url, must_ranged)?; let content = pz.download(filename)?; let mut f = File::create(outputfile)?; f.write_all(&content)?; @@ -45,7 +45,7 @@ fn download(url: &str, filename: &str, outputfile: &str, must_ranged: bool) -> R /// Handler to download the file and pipe it to stdout fn pipe(url: &str, filename: &str, must_ranged: bool) -> Result<()> { let url = Url::parse(url)?; - let mut pz = PartialZip::new(&url, must_ranged)?; + let mut pz = PartialZip::new_check_range(&url, must_ranged)?; let content = pz.download(filename)?; std::io::stdout().write_all(&content)?; Ok(()) @@ -57,7 +57,7 @@ fn main() -> Result<()> { .author(env!("CARGO_PKG_AUTHORS")) .about(env!("CARGO_PKG_DESCRIPTION")) .arg( - Arg::new("must_ranged") + Arg::new("check_range") .short('r') .action(ArgAction::SetTrue) .required(false) @@ -89,25 +89,25 @@ fn main() -> Result<()> { .arg(Arg::new("filename").required(true).index(2)), ) .get_matches(); - let must_ranged = matches.get_flag("must_ranged"); + let check_range = matches.get_flag("check_range"); if let Some(matches) = matches.subcommand_matches("list") { list( matches.get_one::("url").unwrap(), matches.get_flag("files_only"), - must_ranged, + check_range, ) } else if let Some(matches) = matches.subcommand_matches("download") { download( matches.get_one::("url").unwrap(), matches.get_one::("filename").unwrap(), matches.get_one::("outputfile").unwrap(), - must_ranged, + check_range, ) } else if let Some(matches) = matches.subcommand_matches("pipe") { pipe( matches.get_one::("url").unwrap(), matches.get_one::("filename").unwrap(), - must_ranged, + check_range, ) } else { Err(anyhow!("No command matched, try --help")) diff --git a/src/partzip.rs b/src/partzip.rs index db3669b..ecfe966 100644 --- a/src/partzip.rs +++ b/src/partzip.rs @@ -104,8 +104,15 @@ impl PartialZip { /// # Errors /// /// Will return a [`PartialZipError`] enum depending on what error happened - pub fn new(url: &dyn ToString, must_ranged: bool) -> Result { - let reader = PartialReader::new(url, must_ranged)?; + pub fn new(url: &dyn ToString) -> Result { + PartialZip::new_check_range(url, false) + } + /// Create a new [`PartialZip`] + /// # Errors + /// + /// Will return a [`PartialZipError`] enum depending on what error happened + pub fn new_check_range(url: &dyn ToString, check_range: bool) -> Result { + let reader = PartialReader::new_check_range(url, check_range)?; let bufreader = BufReader::new(reader); let archive = ZipArchive::new(bufreader)?; Ok(PartialZip { @@ -170,8 +177,15 @@ impl PartialReader { /// /// # Errors /// Will return a [`PartialZipError`] enum depending on what happened + pub fn new(url: &dyn ToString) -> Result { + PartialReader::new_check_range(url, false) + } + /// Creates a new [`PartialReader`] + /// + /// # Errors + /// Will return a [`PartialZipError`] enum depending on what happened - pub fn new(url: &dyn ToString, must_ranged: bool) -> Result { + pub fn new_check_range(url: &dyn ToString, check_range: bool) -> Result { let url = &url.to_string(); if !utils::url_is_valid(url) { return Err(PartialZipError::InvalidUrl); @@ -188,7 +202,7 @@ impl PartialReader { .to_u64() .ok_or_else(|| std::io::Error::new(ErrorKind::InvalidData, "invalid content length"))?; - if must_ranged { + if check_range { // check if range-request is possible by request 1 byte. if 206 returned, we can make future request. easy.range("0-0")?; easy.nobody(true)?; diff --git a/src/tests.rs b/src/tests.rs index fcd9655..2de8679 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -72,7 +72,7 @@ mod partzip_tests { async fn test_list() -> Result<()> { let address = spawn_server().await?.address; tokio::task::spawn_blocking(move || { - let mut pz = PartialZip::new(&address.join("/files/test.zip")?, false)?; + let mut pz = PartialZip::new(&address.join("/files/test.zip")?)?; let list = pz.list(); assert_eq!( list, @@ -100,7 +100,7 @@ mod partzip_tests { async fn test_download() -> Result<()> { let address = spawn_server().await?.address; tokio::task::spawn_blocking(move || { - let mut pz = PartialZip::new(&address.join("/files/test.zip")?, false)?; + let mut pz = PartialZip::new(&address.join("/files/test.zip")?)?; let downloaded = pz.download("1.txt")?; assert_eq!(downloaded, vec![0x41, 0x41, 0x41, 0x41, 0xa]); let downloaded = pz.download("2.txt")?; @@ -114,7 +114,7 @@ mod partzip_tests { async fn test_download_invalid_file() -> Result<()> { let address = spawn_server().await?.address; tokio::task::spawn_blocking(move || { - let mut pz = PartialZip::new(&address.join("/files/test.zip")?, false)?; + let mut pz = PartialZip::new(&address.join("/files/test.zip")?)?; let downloaded = pz.download("414141.txt"); assert!( matches!( @@ -136,7 +136,6 @@ mod partzip_tests { &address .join("/files/invalid.zip") .expect("cannot join invalid URL"), - false, ); assert!( matches!( @@ -156,7 +155,7 @@ mod partzip_tests { async fn test_invalid_url() -> Result<()> { spawn_server().await?; tokio::task::spawn_blocking(move || { - let pz = PartialZip::new(&"invalid URL", false); + let pz = PartialZip::new(&"invalid URL"); assert!( matches!(pz, Err(PartialZipError::InvalidUrl)), "didn't throw an error with invalid URL" @@ -174,7 +173,7 @@ mod partzip_tests { fn test_file_protocol() -> Result<()> { let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); d.push("testdata/test.zip"); - let mut pz = PartialZip::new(&format!("file://localhost{}", d.display()), false)?; + let mut pz = PartialZip::new(&format!("file://localhost{}", d.display()))?; let list = pz.list(); assert_eq!( list, @@ -201,7 +200,7 @@ mod partzip_tests { fn test_must_ranged_on_not_ranging_protocol() -> Result<()> { let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); d.push("testdata/test.zip"); - let pz = PartialZip::new(&format!("file://localhost{}", d.display()), true); + let pz = PartialZip::new_check_range(&format!("file://localhost{}", d.display()), true); assert!( matches!(pz, Err(PartialZipError::RangeNotSupported)), "didn't throw an error with range not supported" @@ -209,11 +208,23 @@ mod partzip_tests { Ok(()) } + #[tokio::test] + async fn test_range_support() -> Result<()> { + let address = spawn_server().await?.address; + tokio::task::spawn_blocking(move || { + let mut pz = PartialZip::new_check_range(&address.join("/files/test.zip")?, true)?; + let downloaded = pz.download("1.txt")?; + assert_eq!(downloaded, vec![0x41, 0x41, 0x41, 0x41, 0xa]); + Ok(()) + }) + .await? + } + #[tokio::test] async fn test_redirect() -> Result<()> { let address = spawn_server().await?.address; tokio::task::spawn_blocking(move || { - let mut pz = PartialZip::new(&address.join("/redirect")?, false)?; + let mut pz = PartialZip::new(&address.join("/redirect")?)?; let list = pz.list(); assert_eq!( list, diff --git a/tests/cli.rs b/tests/cli.rs index da8c27b..ec89b29 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -63,6 +63,12 @@ fn cli_works() -> Result<()> { .success() .stdout(predicate::str::is_match("1.txt\n2.txt\n").unwrap()); + let mut cmd = Command::cargo_bin("partialzip")?; + cmd.arg("-r").arg("list").arg(&target_arg); + cmd.assert() + .failure() + .stderr(predicate::str::contains("Range request not supported\n")); + let output_file = NamedTempFile::new()?.path().display().to_string(); let mut cmd = Command::cargo_bin("partialzip")?;