Skip to content

Commit

Permalink
Update parsing of extensions, to handle filenames with dots
Browse files Browse the repository at this point in the history
  • Loading branch information
przydatek committed Feb 1, 2024
1 parent 2aa0bee commit fbfcd5b
Showing 1 changed file with 62 additions and 28 deletions.
90 changes: 62 additions & 28 deletions src/asset_util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,19 +422,18 @@ pub fn collect_assets(dir: &Dir, html_transformer: Option<fn(&str) -> String>) -
/// NOTE: behavior is undefined with symlinks (and esp. symlink loops)!
fn collect_assets_rec(dir: &Dir, assets: &mut Vec<Asset>) {
for asset in dir.files() {
let file_bytes = asset.contents().to_vec();
let (content, encoding, content_type) = match file_extension(asset) {
"css" => (file_bytes, ContentEncoding::Identity, ContentType::CSS),
"html" => (file_bytes, ContentEncoding::Identity, ContentType::HTML),
"ico" => (file_bytes, ContentEncoding::Identity, ContentType::ICO),
"json" => (file_bytes, ContentEncoding::Identity, ContentType::JSON),
"js" => (file_bytes, ContentEncoding::Identity, ContentType::JS),
"js.gz" => (file_bytes, ContentEncoding::GZip, ContentType::JS),
"png" => (file_bytes, ContentEncoding::Identity, ContentType::PNG),
"svg" => (file_bytes, ContentEncoding::Identity, ContentType::SVG),
"webp" => (file_bytes, ContentEncoding::Identity, ContentType::WEBP),
"woff2" => (file_bytes, ContentEncoding::Identity, ContentType::WOFF2),
"woff2.gz" => (file_bytes, ContentEncoding::GZip, ContentType::WOFF2),
let content = asset.contents().to_vec();
let (extension, encoding) = file_extension(asset);
let content_type = match extension {
"css" => ContentType::CSS,
"html" => ContentType::HTML,
"ico" => ContentType::ICO,
"json" => ContentType::JSON,
"js" => ContentType::JS,
"png" => ContentType::PNG,
"svg" => ContentType::SVG,
"webp" => ContentType::WEBP,
"woff2" => ContentType::WOFF2,
ext => panic!(
"Unknown asset type '{}' for asset '{}'",
ext,
Expand Down Expand Up @@ -465,21 +464,29 @@ fn collect_assets_rec(dir: &Dir, assets: &mut Vec<Asset>) {
}
}

/// Returns the portion of the filename after the first dot.
/// This corresponds to the file extension for the assets handled by this canister.
///
/// The builtin `extension` method on `Path` does not work for file extensions with multiple dots
/// such as `.js.gz`.
fn file_extension<'a>(asset: &'a File) -> &'a str {
asset
.path()
.file_name()
.unwrap()
.to_str()
.unwrap()
.split_once('.')
.unwrap()
.1
/// Returns the extension of the given file, and the encoding type.
/// If the text after the last dot is "gz" (i.e. this is a gzipped file), then the extension
/// is the text after the second to last dot and the last dot in the file name
/// (e.g. "js" for "some.gzipped.file.js.gz"), and the encoding is `ContentEncoding::GZip`.
/// Otherwise the extension is the text after the last dot in the file name,
/// and the encoding is `ContentEncoding::Identity`.
/// This corresponds to the file extension for the assets handled by this crate.
fn file_extension<'a>(asset: &'a File) -> (&'a str, ContentEncoding) {
let extension = asset.path().extension().unwrap().to_str().unwrap();
if extension == "gz" {
let type_extension = asset
.path()
.file_name()
.unwrap()
.to_str()
.unwrap()
.split('.')
.nth_back(1)
.unwrap();
return (type_extension, ContentEncoding::GZip);
} else {
return (extension, ContentEncoding::Identity);
}
}

/// Returns the URL paths for a given asset filepath. For instance:
Expand Down Expand Up @@ -605,3 +612,30 @@ fn test_filepath_urlpaths() {
],
);
}

#[test]
fn should_return_correct_extension() {
let path_extension_encoding = [
("path1/some_css_file.css", "css", ContentEncoding::Identity),
("path2/an_html_file.html", "html", ContentEncoding::Identity),
("path3/an_ico_file.ico", "ico", ContentEncoding::Identity),
("path4/json_file.json", "json", ContentEncoding::Identity),
("path5/js_file.js", "js", ContentEncoding::Identity),
("path6/gzipped_js_file.js.gz", "js", ContentEncoding::GZip),
("path7/a_png_file.png", "png", ContentEncoding::Identity),
("path8/svg_file.svg", "svg", ContentEncoding::Identity),
("path9/webp_file.webp", "webp", ContentEncoding::Identity),
("path10/a_file.woff2", "woff2", ContentEncoding::Identity),
("path11/gz_woff2.woff2.gz", "woff2", ContentEncoding::GZip),
("path.dots/ico_file.ico", "ico", ContentEncoding::Identity),
("path13/file.with.dots.js", "js", ContentEncoding::Identity),
("path14.dot/gz_js_file.js.gz", "js", ContentEncoding::GZip),
("path15.dots/.dots.woff2.gz", "woff2", ContentEncoding::GZip),
];
for (path, expected_extension, expected_encoding) in path_extension_encoding {
assert_eq!(
file_extension(&File::new(path, &[42])),
(expected_extension, expected_encoding)
);
}
}

0 comments on commit fbfcd5b

Please sign in to comment.