Skip to content

Commit

Permalink
Merge pull request #95 from blandger/fix_parametrized_remote_url_down…
Browse files Browse the repository at this point in the history
…load

Correct downloading remote resource with parametrized url
  • Loading branch information
blandger authored Mar 25, 2024
2 parents 14aa2eb + b4513a7 commit cd53a21
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 6 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ html_parser = "0.7.0"
url = "2.3"
ureq = "2.9"
const_format = "0.2.31"
uuid = "1.8"

[dev-dependencies]
tempfile = "3"
Expand Down
23 changes: 22 additions & 1 deletion src/resources/retrieve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub(crate) trait ContentRetriever {
fs::create_dir_all(cache_dir)?;
}
debug!("Downloading asset : {}", url);
let mut file = OpenOptions::new().create(true).write(true).open(dest)?;
let mut file = OpenOptions::new().create(true).truncate(true).write(true).open(dest)?;
let mut resp = self.retrieve(url.as_str())?;
io::copy(&mut resp, &mut file)?;
debug!("Downloaded asset by '{}'", url);
Expand Down Expand Up @@ -117,6 +117,27 @@ mod tests {
panic!("{}", r.unwrap_err().to_string());
}

#[test]
fn download_parametrized_avatar_image() {
use std::io::Read;

struct TestHandler;
impl ContentRetriever for TestHandler {
fn retrieve(&self, _url: &str) -> Result<BoxRead, Error> {
Ok(Box::new("Downloaded content".as_bytes()))
}
}
let cr = TestHandler {};
let a = temp_remote_asset("https://avatars.githubusercontent.com/u/274803?v=4").unwrap();
let r = cr.download(&a);
assert!(r.is_ok());

let mut buffer = String::new();
let mut f = std::fs::File::open(&a.location_on_disk).unwrap();
f.read_to_string(&mut buffer).unwrap();
assert_eq!(buffer, "Downloaded content");
}

fn temp_remote_asset(url: &str) -> Result<Asset, Error> {
let tmp_dir = TempDir::new().unwrap();
let dest_dir = tmp_dir.path().join("mdbook-epub");
Expand Down
22 changes: 21 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use pulldown_cmark::{Options, Parser};
use std::ffi::OsStr;
use std::path::{Component, Path, PathBuf};
use url::Url;
use uuid::Uuid;

pub(crate) fn create_new_pull_down_parser(text: &str) -> Parser<'_, '_> {
let mut opts = Options::empty();
Expand Down Expand Up @@ -40,24 +41,43 @@ pub fn normalize_path(path: &Path) -> PathBuf {
ret
}

/// Generate file name + extension from supplied remote URL.
/// If url does not contain file extension because of 'parametrized url'
/// then file's extension is generated as UUID4 value and file name
/// is hashed from URL itself.
pub(crate) fn hash_link(url: &Url) -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

let mut hasher = DefaultHasher::new();
url.hash(&mut hasher);
let path = PathBuf::from(url.path());
let _generated_file_extension = Uuid::new_v4().to_string();
let ext = path
.extension()
.and_then(OsStr::to_str)
.unwrap_or_else(|| panic!("Unable to extract file ext from {url}"));
.unwrap_or(_generated_file_extension.as_str());
format!("{:x}.{}", hasher.finish(), ext)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_hash_named_url_with_extention() {
let test_url = "https://www.rust-lang.org/static/images/rust-logo-blk.svg";
let hashed_filename = hash_link(&test_url.parse::<Url>().unwrap());
assert_eq!("b20b2723e874918.svg", hashed_filename);
}

#[test]
fn test_hash_parametrized_url_no_extension() {
let test_avatar_url = "https://avatars.githubusercontent.com/u/274803?v=4";
let hashed_filename = hash_link(&test_avatar_url.parse::<Url>().unwrap());
assert!(hashed_filename.starts_with("4dbdb25800b6fa1b."));
}

#[cfg(not(target_os = "windows"))]
#[test]
fn test_normalize_path() {
Expand Down
13 changes: 12 additions & 1 deletion tests/dummy/src/01_getting_started/02_article.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,15 @@
We all love how Rust empowers us to write fast, safe software.

**Fig 1: Before and after example**
![swap_problem](../assets/rust-logo.png)
![swap_problem](../assets/rust-logo.png)


```powershell
if (Test-Path "myproject.zip") {
del "myproject.zip";
}
& "c:\Program Files\7-Zip\7z.exe" a myproject.zip .\myproject\ "-xr!.git" "-xr!.gitignore"
pause
```

![Image](https://avatars.githubusercontent.com/u/274803?v=4)
2 changes: 1 addition & 1 deletion tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ fn rendered_document_contains_all_chapter_files_and_assets() {
let mut doc = generate_epub().unwrap();
debug!("Number of internal epub resources = {:?}", doc.0.resources);
// number of internal epub resources for dummy test book
assert_eq!(8, doc.0.resources.len());
assert_eq!(9, doc.0.resources.len());
assert_eq!(2, doc.0.spine.len());
assert_eq!(doc.0.mdata("title").unwrap(), "DummyBook");
assert_eq!(doc.0.mdata("language").unwrap(), "en");
Expand Down

0 comments on commit cd53a21

Please sign in to comment.