|
@@ -25,73 +25,62 @@ fn module_loader(root_name: &str) -> String {
|
|
|
|
|
|
pub(super) fn desktop_handler(
|
|
|
request: &Request<Vec<u8>>,
|
|
|
- asset_root: Option<PathBuf>,
|
|
|
custom_head: Option<String>,
|
|
|
custom_index: Option<String>,
|
|
|
root_name: &str,
|
|
|
) -> Result<Response<Vec<u8>>> {
|
|
|
- // 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 </body> 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("</body>", &format!("{}</body>", 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 -->", &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 -->", &custom_head);
|
|
|
+ }
|
|
|
+
|
|
|
+ template
|
|
|
+ .replace("<!-- MODULE LOADER -->", &module_loader(root_name))
|
|
|
+ .into_bytes()
|
|
|
}
|
|
|
- template = template.replace("<!-- MODULE LOADER -->", &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)?)
|
|
|
+ };
|
|
|
+
|
|
|
+ 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)
|
|
|
+ .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,7 +117,7 @@ fn get_asset_root() -> Option<PathBuf> {
|
|
|
}
|
|
|
|
|
|
/// Get the mime type from a path-like string
|
|
|
-fn get_mime_from_path(trimmed: &str) -> Result<&str> {
|
|
|
+fn get_mime_from_path(trimmed: &Path) -> Result<&'static str> {
|
|
|
if trimmed.ends_with(".svg") {
|
|
|
return Ok("image/svg+xml");
|
|
|
}
|
|
@@ -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: &Path) -> &'static str {
|
|
|
+ match trimmed.extension().and_then(|e| e.to_str()) {
|
|
|
Some("bin") => "application/octet-stream",
|
|
|
Some("css") => "text/css",
|
|
|
Some("csv") => "text/csv",
|