use crate::{env::EnvBinding, RequestInit, Result}; use std::convert::TryInto; use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen_futures::JsFuture; #[cfg(feature = "http")] use crate::HttpResponse; use crate::{Request, Response}; /// A struct for invoking fetch events to other Workers. #[derive(Debug, Clone)] pub struct Fetcher(worker_sys::Fetcher); #[cfg(not(feature = "http"))] type FetchResponseType = Response; #[cfg(feature = "http")] type FetchResponseType = HttpResponse; impl Fetcher { /// Invoke a fetch event in a worker with a url and optionally a [RequestInit]. /// /// Return type is [`Response`](crate::Response) unless `http` feature is enabled /// and then it is [`http::Response`]. pub async fn fetch( &self, url: impl Into, init: Option, ) -> Result { let path = url.into(); let promise = match init { Some(ref init) => self.0.fetch_with_str_and_init(&path, &init.into()), None => self.0.fetch_with_str(&path), }?; let resp_sys: web_sys::Response = JsFuture::from(promise).await?.dyn_into()?; #[cfg(not(feature = "http"))] let result = Ok(Response::from(resp_sys)); #[cfg(feature = "http")] let result = crate::response_from_wasm(resp_sys); result } /// Invoke a fetch event with an existing [Request]. /// /// Argument type is [`Request`](crate::Request) or [`http::Request`]. /// /// Return type is [`Response`](crate::Response) unless `http` feature is enabled /// and then it is [`http::Response`]. pub async fn fetch_request(&self, request: T) -> Result where T: TryInto, crate::Error: From, { let req = request.try_into()?; let promise = self.0.fetch(req.inner())?; let resp_sys: web_sys::Response = JsFuture::from(promise).await?.dyn_into()?; let response = Response::from(resp_sys); #[cfg(feature = "http")] let result = response.try_into(); #[cfg(not(feature = "http"))] let result = Ok(response); result } /// Convert Fetcher into user-defined RPC interface. /// ``` /// #[wasm_bindgen] /// extern "C" { /// #[wasm_bindgen(extends=js_sys::Object)] /// #[derive(Debug, Clone, PartialEq, Eq)] /// pub type MyRpcInterface; /// /// #[wasm_bindgen(method, catch)] /// pub fn add( /// this: &MyRpcInterface, /// a: u32, /// b: u32, /// ) -> std::result::Result; /// } /// /// let rpc: MyRpcInterface = fetcher.into_rpc(); /// let result = rpc.add(1, 2); /// ``` pub fn into_rpc(self) -> T { self.0.unchecked_into() } } impl EnvBinding for Fetcher { const TYPE_NAME: &'static str = "Fetcher"; } impl JsCast for Fetcher { fn instanceof(val: &wasm_bindgen::JsValue) -> bool { val.is_instance_of::() } fn unchecked_from_js(val: wasm_bindgen::JsValue) -> Self { Self(val.into()) } fn unchecked_from_js_ref(val: &wasm_bindgen::JsValue) -> &Self { unsafe { &*(val as *const JsValue as *const Self) } } } impl From for JsValue { fn from(service: Fetcher) -> Self { JsValue::from(service.0) } } impl AsRef for Fetcher { fn as_ref(&self) -> &wasm_bindgen::JsValue { &self.0 } } impl From for Fetcher { fn from(inner: worker_sys::Fetcher) -> Self { Self(inner) } }