diff --git a/examples/custom_assets.rs b/examples/custom_assets.rs index 86d82acf4..ae37ecd4e 100644 --- a/examples/custom_assets.rs +++ b/examples/custom_assets.rs @@ -8,7 +8,8 @@ fn app(cx: Scope) -> Element { cx.render(rsx! { div { "This should show an image:" - img { src: "examples/assets/logo.png", } + img { src: "examples/assets/logo.png" } + img { src: "/Users/jonkelley/Desktop/blitz.png" } } }) } diff --git a/packages/desktop/src/protocol.rs b/packages/desktop/src/protocol.rs index 8835078f2..5512f12c4 100644 --- a/packages/desktop/src/protocol.rs +++ b/packages/desktop/src/protocol.rs @@ -25,73 +25,62 @@ fn module_loader(root_name: &str) -> String { pub(super) fn desktop_handler( request: &Request>, - asset_root: Option, custom_head: Option, custom_index: Option, root_name: &str, ) -> Result>> { - // Any content that uses the `dioxus://` scheme will be shuttled through this handler as a "special case". - // For now, we only serve two pieces of content which get included as bytes into the final binary. - let path = request.uri().to_string().replace("dioxus://", ""); - - // all assets should be called from index.html - let trimmed = path.trim_start_matches("index.html/"); - - if trimmed.is_empty() { + // If the request is for the root, we'll serve the index.html file. + if request.uri().path() == "/" { // If a custom index is provided, just defer to that, expecting the user to know what they're doing. // we'll look for the closing tag and insert our little module loader there. - if let Some(custom_index) = custom_index { - let rendered = custom_index + let body = match custom_index { + Some(custom_index) => custom_index .replace("", &format!("{}", module_loader(root_name))) - .into_bytes(); - Response::builder() - .header("Content-Type", "text/html") - .body(rendered) - .map_err(From::from) - } else { - // Otherwise, we'll serve the default index.html and apply a custom head if that's specified. - let mut template = include_str!("./index.html").to_string(); - if let Some(custom_head) = custom_head { - template = template.replace("", &custom_head); + .into_bytes(), + + None => { + // Otherwise, we'll serve the default index.html and apply a custom head if that's specified. + let mut template = include_str!("./index.html").to_string(); + + if let Some(custom_head) = custom_head { + template = template.replace("", &custom_head); + } + + template + .replace("", &module_loader(root_name)) + .into_bytes() } - template = template.replace("", &module_loader(root_name)); + }; - Response::builder() - .header("Content-Type", "text/html") - .body(template.into_bytes()) - .map_err(From::from) - } - } else if trimmed == "index.js" { - Response::builder() - .header("Content-Type", "text/javascript") - .body(dioxus_interpreter_js::INTERPRETER_JS.as_bytes().to_vec()) - .map_err(From::from) - } else { - let asset_root = asset_root - .unwrap_or_else(|| get_asset_root().unwrap_or_else(|| Path::new(".").to_path_buf())) - .canonicalize()?; - - let asset = asset_root.join(trimmed).canonicalize()?; - - if !asset.starts_with(asset_root) { - return Response::builder() - .status(StatusCode::FORBIDDEN) - .body(String::from("Forbidden").into_bytes()) - .map_err(From::from); - } - - if !asset.exists() { - return Response::builder() - .status(StatusCode::NOT_FOUND) - .body(String::from("Not Found").into_bytes()) - .map_err(From::from); - } - - Response::builder() - .header("Content-Type", get_mime_from_path(trimmed)?) - .body(std::fs::read(asset)?) - .map_err(From::from) + return Response::builder() + .header("Content-Type", "text/html") + .body(body) + .map_err(From::from); } + + // Else, try to serve a file from the filesystem. + let path = PathBuf::from(request.uri().path().trim_start_matches("/")); + + // If the path is relative, we'll try to serve it from the assets directory. + let mut asset = get_asset_root() + .unwrap_or_else(|| Path::new(".").to_path_buf()) + .join(&path); + + if !asset.exists() { + asset = PathBuf::from("/").join(path); + } + + if asset.exists() { + return Response::builder() + .header("Content-Type", get_mime_from_path(&asset)?) + .body(std::fs::read(asset)?) + .map_err(From::from); + } + + Response::builder() + .status(StatusCode::NOT_FOUND) + .body(String::from("Not Found").into_bytes()) + .map_err(From::from) } #[allow(unreachable_code)] @@ -128,12 +117,12 @@ fn get_asset_root() -> Option { } /// Get the mime type from a path-like string -fn get_mime_from_path(trimmed: &str) -> Result<&str> { +fn get_mime_from_path(trimmed: &PathBuf) -> Result<&'static str> { if trimmed.ends_with(".svg") { return Ok("image/svg+xml"); } - let res = match infer::get_from_path(trimmed)?.map(|f| f.mime_type()) { + let res = match infer::get_from_path(trimmed.clone())?.map(|f| f.mime_type()) { Some(t) if t == "text/plain" => get_mime_by_ext(trimmed), Some(f) => f, None => get_mime_by_ext(trimmed), @@ -143,9 +132,8 @@ fn get_mime_from_path(trimmed: &str) -> Result<&str> { } /// Get the mime type from a URI using its extension -fn get_mime_by_ext(trimmed: &str) -> &str { - let suffix = trimmed.split('.').last(); - match suffix { +fn get_mime_by_ext(trimmed: &PathBuf) -> &'static str { + match trimmed.extension().and_then(|e| e.to_str()) { Some("bin") => "application/octet-stream", Some("css") => "text/css", Some("csv") => "text/csv", diff --git a/packages/desktop/src/webview.rs b/packages/desktop/src/webview.rs index 721f37d94..a8f437614 100644 --- a/packages/desktop/src/webview.rs +++ b/packages/desktop/src/webview.rs @@ -18,7 +18,6 @@ pub fn build( let window = builder.build(event_loop).unwrap(); let file_handler = cfg.file_drop_handler.take(); let custom_head = cfg.custom_head.clone(); - let resource_dir = cfg.resource_dir.clone(); let index_file = cfg.custom_index.clone(); let root_name = cfg.root_name.clone(); @@ -46,13 +45,7 @@ pub fn build( } }) .with_custom_protocol(String::from("dioxus"), move |r| { - protocol::desktop_handler( - r, - resource_dir.clone(), - custom_head.clone(), - index_file.clone(), - &root_name, - ) + protocol::desktop_handler(r, custom_head.clone(), index_file.clone(), &root_name) }) .with_file_drop_handler(move |window, evet| { file_handler