[go: up one dir, main page]

worker/
fetcher.rs

1use crate::{env::EnvBinding, RequestInit, Result};
2#[cfg(feature = "http")]
3use std::convert::TryInto;
4use wasm_bindgen::{JsCast, JsValue};
5use wasm_bindgen_futures::JsFuture;
6
7#[cfg(feature = "http")]
8use crate::{HttpRequest, HttpResponse};
9use crate::{Request, Response};
10/// A struct for invoking fetch events to other Workers.
11#[derive(Debug, Clone)]
12pub struct Fetcher(worker_sys::Fetcher);
13
14#[cfg(not(feature = "http"))]
15type FetchResponseType = Response;
16#[cfg(feature = "http")]
17type FetchResponseType = HttpResponse;
18
19#[cfg(not(feature = "http"))]
20type FetchRequestType = Request;
21#[cfg(feature = "http")]
22type FetchRequestType = HttpRequest;
23
24impl Fetcher {
25    /// Invoke a fetch event in a worker with a url and optionally a [RequestInit].
26    ///
27    /// Return type is [`Response`](crate::Response) unless `http` feature is enabled
28    /// and then it is [`http::Response<worker::Body>`].
29    pub async fn fetch(
30        &self,
31        url: impl Into<String>,
32        init: Option<RequestInit>,
33    ) -> Result<FetchResponseType> {
34        let path = url.into();
35        let promise = match init {
36            Some(ref init) => self.0.fetch_with_str_and_init(&path, &init.into()),
37            None => self.0.fetch_with_str(&path),
38        }?;
39
40        let resp_sys: web_sys::Response = JsFuture::from(promise).await?.dyn_into()?;
41        #[cfg(not(feature = "http"))]
42        let result = Ok(Response::from(resp_sys));
43        #[cfg(feature = "http")]
44        let result = crate::response_from_wasm(resp_sys);
45        result
46    }
47
48    /// Invoke a fetch event with an existing [Request].
49    ///
50    /// Argument type is [`Request`](crate::Request) unless `http` feature is enabled
51    /// and then it is [`http::Request<worker::Body>`].
52    ///
53    /// Return type is [`Response`](crate::Response) unless `http` feature is enabled
54    /// and then it is [`http::Response<worker::Body>`].
55    pub async fn fetch_request(&self, request: FetchRequestType) -> Result<FetchResponseType> {
56        #[cfg(feature = "http")]
57        let req = TryInto::<Request>::try_into(request)?;
58        #[cfg(not(feature = "http"))]
59        let req = request;
60        let promise = self.0.fetch(req.inner())?;
61        let resp_sys: web_sys::Response = JsFuture::from(promise).await?.dyn_into()?;
62        let response = Response::from(resp_sys);
63        #[cfg(feature = "http")]
64        let result = response.try_into();
65        #[cfg(not(feature = "http"))]
66        let result = Ok(response);
67        result
68    }
69
70    /// Convert Fetcher into user-defined RPC interface.
71    /// ```
72    /// #[wasm_bindgen]
73    /// extern "C" {
74    ///     #[wasm_bindgen(extends=js_sys::Object)]
75    ///     #[derive(Debug, Clone, PartialEq, Eq)]
76    ///     pub type MyRpcInterface;
77    ///
78    ///     #[wasm_bindgen(method, catch)]
79    ///     pub fn add(
80    ///         this: &MyRpcInterface,
81    ///         a: u32,
82    ///         b: u32,
83    ///     ) -> std::result::Result<js_sys::Promise, JsValue>;
84    /// }
85    ///
86    /// let rpc: MyRpcInterface = fetcher.into_rpc();
87    /// let result = rpc.add(1, 2);
88    /// ```
89    pub fn into_rpc<T: JsCast>(self) -> T {
90        self.0.unchecked_into()
91    }
92}
93
94impl EnvBinding for Fetcher {
95    const TYPE_NAME: &'static str = "Fetcher";
96}
97
98impl JsCast for Fetcher {
99    fn instanceof(val: &wasm_bindgen::JsValue) -> bool {
100        val.is_instance_of::<Fetcher>()
101    }
102
103    fn unchecked_from_js(val: wasm_bindgen::JsValue) -> Self {
104        Self(val.into())
105    }
106
107    fn unchecked_from_js_ref(val: &wasm_bindgen::JsValue) -> &Self {
108        unsafe { &*(val as *const JsValue as *const Self) }
109    }
110}
111
112impl From<Fetcher> for JsValue {
113    fn from(service: Fetcher) -> Self {
114        JsValue::from(service.0)
115    }
116}
117
118impl AsRef<wasm_bindgen::JsValue> for Fetcher {
119    fn as_ref(&self) -> &wasm_bindgen::JsValue {
120        &self.0
121    }
122}
123
124impl From<worker_sys::Fetcher> for Fetcher {
125    fn from(inner: worker_sys::Fetcher) -> Self {
126        Self(inner)
127    }
128}