summaryrefslogtreecommitdiff
path: root/ext/fetch/fs_fetch_handler.rs
diff options
context:
space:
mode:
authorKitson Kelly <me@kitsonkelly.com>2021-11-01 15:29:46 +1100
committerGitHub <noreply@github.com>2021-11-01 15:29:46 +1100
commitd3662e487d9ff94a09a2fa96598bf0a41666a7f2 (patch)
treeef44499ca2e38c4005de1a5b566695ebb0526aed /ext/fetch/fs_fetch_handler.rs
parentd080f1c9651b34a2887473bd468495b72ea8f8b4 (diff)
feat(ext/fetch): support fetching local files (#12545)
Closes #11925 Closes #2150 Co-authored-by: Bert Belder <bertbelder@gmail.com>
Diffstat (limited to 'ext/fetch/fs_fetch_handler.rs')
-rw-r--r--ext/fetch/fs_fetch_handler.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/ext/fetch/fs_fetch_handler.rs b/ext/fetch/fs_fetch_handler.rs
new file mode 100644
index 000000000..82cbc4ecb
--- /dev/null
+++ b/ext/fetch/fs_fetch_handler.rs
@@ -0,0 +1,52 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
+use crate::CancelHandle;
+use crate::CancelableResponseFuture;
+use crate::FetchHandler;
+use crate::FetchRequestBodyResource;
+
+use deno_core::error::type_error;
+use deno_core::futures::FutureExt;
+use deno_core::futures::TryFutureExt;
+use deno_core::url::Url;
+use deno_core::CancelFuture;
+use reqwest::StatusCode;
+use std::rc::Rc;
+use tokio_util::io::ReaderStream;
+
+/// An implementation which tries to read file URLs from the file system via
+/// tokio::fs.
+#[derive(Clone)]
+pub struct FsFetchHandler;
+
+impl FetchHandler for FsFetchHandler {
+ fn fetch_file(
+ &mut self,
+ url: Url,
+ ) -> (
+ CancelableResponseFuture,
+ Option<FetchRequestBodyResource>,
+ Option<Rc<CancelHandle>>,
+ ) {
+ let cancel_handle = CancelHandle::new_rc();
+ let response_fut = async move {
+ let path = url.to_file_path()?;
+ let file = tokio::fs::File::open(path).map_err(|_| ()).await?;
+ let stream = ReaderStream::new(file);
+ let body = reqwest::Body::wrap_stream(stream);
+ let response = http::Response::builder()
+ .status(StatusCode::OK)
+ .body(body)
+ .map_err(|_| ())?
+ .into();
+ Ok::<_, ()>(response)
+ }
+ .map_err(move |_| {
+ type_error("NetworkError when attempting to fetch resource.")
+ })
+ .or_cancel(&cancel_handle)
+ .boxed_local();
+
+ (response_fut, None, Some(cancel_handle))
+ }
+}