Browse Source

fix(core): use `safe_block_on` (#7047)

fixes regression introduced in 45330e38193d0b2a01aa926aec433acc6b8f6597

ref: https://github.com/tauri-apps/tauri/issues/6375#issuecomment-1560063696
Amr Bashir 2 years ago
parent
commit
2317913b71
1 changed files with 98 additions and 87 deletions
  1. 98 87
      core/tauri/src/asset_protocol.rs

+ 98 - 87
core/tauri/src/asset_protocol.rs

@@ -46,7 +46,7 @@ pub fn asset_protocol_handler(
 
 
   let mut resp = ResponseBuilder::new().header("Access-Control-Allow-Origin", &window_origin);
   let mut resp = ResponseBuilder::new().header("Access-Control-Allow-Origin", &window_origin);
 
 
-  crate::async_runtime::block_on(async move {
+  let (mut file, len, mime_type, read_bytes) = crate::async_runtime::safe_block_on(async move {
     let mut file = File::open(&path).await?;
     let mut file = File::open(&path).await?;
 
 
     // get file length
     // get file length
@@ -72,91 +72,99 @@ pub fn asset_protocol_handler(
       )
       )
     };
     };
 
 
-    resp = resp.header(CONTENT_TYPE, &mime_type);
-
-    // handle 206 (partial range) http requests
-    let response = if let Some(range_header) = request
-      .headers()
-      .get("range")
-      .and_then(|r| r.to_str().map(|r| r.to_string()).ok())
-    {
-      resp = resp.header(ACCEPT_RANGES, "bytes");
-
-      let not_satisfiable = || {
-        ResponseBuilder::new()
-          .status(StatusCode::RANGE_NOT_SATISFIABLE)
-          .header(CONTENT_RANGE, format!("bytes */{len}"))
-          .body(vec![])
-      };
-
-      // parse range header
-      let ranges = if let Ok(ranges) = HttpRange::parse(&range_header, len) {
-        ranges
-          .iter()
-          // map the output to spec range <start-end>, example: 0-499
-          .map(|r| (r.start, r.start + r.length - 1))
-          .collect::<Vec<_>>()
-      } else {
-        return not_satisfiable();
-      };
+    Ok::<(File, u64, String, Option<Vec<u8>>), anyhow::Error>((file, len, mime_type, read_bytes))
+  })?;
 
 
-      /// The Maximum bytes we send in one range
-      const MAX_LEN: u64 = 1000 * 1024;
+  resp = resp.header(CONTENT_TYPE, &mime_type);
 
 
-      // single-part range header
-      if ranges.len() == 1 {
-        let &(start, mut end) = ranges.first().unwrap();
+  // handle 206 (partial range) http requests
+  let response = if let Some(range_header) = request
+    .headers()
+    .get("range")
+    .and_then(|r| r.to_str().map(|r| r.to_string()).ok())
+  {
+    resp = resp.header(ACCEPT_RANGES, "bytes");
 
 
-        // check if a range is not satisfiable
-        //
-        // this should be already taken care of by the range parsing library
-        // but checking here again for extra assurance
-        if start >= len || end >= len || end < start {
-          return not_satisfiable();
-        }
+    let not_satisfiable = || {
+      ResponseBuilder::new()
+        .status(StatusCode::RANGE_NOT_SATISFIABLE)
+        .header(CONTENT_RANGE, format!("bytes */{len}"))
+        .body(vec![])
+    };
+
+    // parse range header
+    let ranges = if let Ok(ranges) = HttpRange::parse(&range_header, len) {
+      ranges
+        .iter()
+        // map the output to spec range <start-end>, example: 0-499
+        .map(|r| (r.start, r.start + r.length - 1))
+        .collect::<Vec<_>>()
+    } else {
+      return not_satisfiable();
+    };
+
+    /// The Maximum bytes we send in one range
+    const MAX_LEN: u64 = 1000 * 1024;
+
+    // single-part range header
+    if ranges.len() == 1 {
+      let &(start, mut end) = ranges.first().unwrap();
 
 
-        // adjust end byte for MAX_LEN
-        end = start + (end - start).min(len - start).min(MAX_LEN - 1);
+      // check if a range is not satisfiable
+      //
+      // this should be already taken care of by the range parsing library
+      // but checking here again for extra assurance
+      if start >= len || end >= len || end < start {
+        return not_satisfiable();
+      }
 
 
-        // calculate number of bytes needed to be read
-        let nbytes = end + 1 - start;
+      // adjust end byte for MAX_LEN
+      end = start + (end - start).min(len - start).min(MAX_LEN - 1);
 
 
+      // calculate number of bytes needed to be read
+      let nbytes = end + 1 - start;
+
+      let buf = crate::async_runtime::safe_block_on(async move {
         let mut buf = Vec::with_capacity(nbytes as usize);
         let mut buf = Vec::with_capacity(nbytes as usize);
         file.seek(SeekFrom::Start(start)).await?;
         file.seek(SeekFrom::Start(start)).await?;
         file.take(nbytes).read_to_end(&mut buf).await?;
         file.take(nbytes).read_to_end(&mut buf).await?;
+        Ok::<Vec<u8>, anyhow::Error>(buf)
+      })?;
 
 
-        resp = resp.header(CONTENT_RANGE, format!("bytes {start}-{end}/{len}"));
-        resp = resp.header(CONTENT_LENGTH, end + 1 - start);
-        resp = resp.status(StatusCode::PARTIAL_CONTENT);
-        resp.body(buf)
-      } else {
+      resp = resp.header(CONTENT_RANGE, format!("bytes {start}-{end}/{len}"));
+      resp = resp.header(CONTENT_LENGTH, end + 1 - start);
+      resp = resp.status(StatusCode::PARTIAL_CONTENT);
+      resp.body(buf)
+    } else {
+      let ranges = ranges
+        .iter()
+        .filter_map(|&(start, mut end)| {
+          // filter out unsatisfiable ranges
+          //
+          // this should be already taken care of by the range parsing library
+          // but checking here again for extra assurance
+          if start >= len || end >= len || end < start {
+            None
+          } else {
+            // adjust end byte for MAX_LEN
+            end = start + (end - start).min(len - start).min(MAX_LEN - 1);
+            Some((start, end))
+          }
+        })
+        .collect::<Vec<_>>();
+
+      let boundary = random_boundary();
+      let boundary_sep = format!("\r\n--{boundary}\r\n");
+      let boundary_closer = format!("\r\n--{boundary}\r\n");
+
+      resp = resp.header(
+        CONTENT_TYPE,
+        format!("multipart/byteranges; boundary={boundary}"),
+      );
+
+      let buf = crate::async_runtime::safe_block_on(async move {
         // multi-part range header
         // multi-part range header
         let mut buf = Vec::new();
         let mut buf = Vec::new();
-        let ranges = ranges
-          .iter()
-          .filter_map(|&(start, mut end)| {
-            // filter out unsatisfiable ranges
-            //
-            // this should be already taken care of by the range parsing library
-            // but checking here again for extra assurance
-            if start >= len || end >= len || end < start {
-              None
-            } else {
-              // adjust end byte for MAX_LEN
-              end = start + (end - start).min(len - start).min(MAX_LEN - 1);
-              Some((start, end))
-            }
-          })
-          .collect::<Vec<_>>();
-
-        let boundary = random_boundary();
-        let boundary_sep = format!("\r\n--{boundary}\r\n");
-        let boundary_closer = format!("\r\n--{boundary}\r\n");
-
-        resp = resp.header(
-          CONTENT_TYPE,
-          format!("multipart/byteranges; boundary={boundary}"),
-        );
 
 
         for (end, start) in ranges {
         for (end, start) in ranges {
           // a new range is being written, write the range boundary
           // a new range is being written, write the range boundary
@@ -184,24 +192,27 @@ pub fn asset_protocol_handler(
         // all ranges have been written, write the closing boundary
         // all ranges have been written, write the closing boundary
         buf.write_all(boundary_closer.as_bytes()).await?;
         buf.write_all(boundary_closer.as_bytes()).await?;
 
 
-        resp.body(buf)
-      }
+        Ok::<Vec<u8>, anyhow::Error>(buf)
+      })?;
+      resp.body(buf)
+    }
+  } else {
+    // avoid reading the file if we already read it
+    // as part of mime type detection
+    let buf = if let Some(b) = read_bytes {
+      b
     } else {
     } else {
-      // avoid reading the file if we already read it
-      // as part of mime type detection
-      let buf = if let Some(b) = read_bytes {
-        b
-      } else {
+      crate::async_runtime::safe_block_on(async move {
         let mut local_buf = Vec::with_capacity(len as usize);
         let mut local_buf = Vec::with_capacity(len as usize);
         file.read_to_end(&mut local_buf).await?;
         file.read_to_end(&mut local_buf).await?;
-        local_buf
-      };
-      resp = resp.header(CONTENT_LENGTH, len);
-      resp.body(buf)
+        Ok::<Vec<u8>, anyhow::Error>(local_buf)
+      })?
     };
     };
+    resp = resp.header(CONTENT_LENGTH, len);
+    resp.body(buf)
+  };
 
 
-    response
-  })
+  response
 }
 }
 
 
 fn random_boundary() -> String {
 fn random_boundary() -> String {