[go: up one dir, main page]

worker/
fetcher.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::{env::EnvBinding, RequestInit, Result};
#[cfg(feature = "http")]
use std::convert::TryInto;
use wasm_bindgen::{JsCast, JsValue};
use wasm_bindgen_futures::JsFuture;

#[cfg(feature = "http")]
use crate::{HttpRequest, HttpResponse};
use crate::{Request, Response};
/// A struct for invoking fetch events to other Workers.
#[derive(Clone)]
pub struct Fetcher(worker_sys::Fetcher);

#[cfg(not(feature = "http"))]
type FetchResponseType = Response;
#[cfg(feature = "http")]
type FetchResponseType = HttpResponse;

#[cfg(not(feature = "http"))]
type FetchRequestType = Request;
#[cfg(feature = "http")]
type FetchRequestType = HttpRequest;

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<worker::Body>`].
    pub async fn fetch(
        &self,
        url: impl Into<String>,
        init: Option<RequestInit>,
    ) -> Result<FetchResponseType> {
        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) unless `http` feature is enabled
    /// and then it is [`http::Request<worker::Body>`].
    ///
    /// Return type is [`Response`](crate::Response) unless `http` feature is enabled
    /// and then it is [`http::Response<worker::Body>`].
    pub async fn fetch_request(&self, request: FetchRequestType) -> Result<FetchResponseType> {
        #[cfg(feature = "http")]
        let req = TryInto::<Request>::try_into(request)?;
        #[cfg(not(feature = "http"))]
        let req = request;
        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<js_sys::Promise, JsValue>;
    /// }
    ///
    /// let rpc: MyRpcInterface = fetcher.into_rpc();
    /// let result = rpc.add(1, 2);
    /// ```
    pub fn into_rpc<T: JsCast>(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::<Fetcher>()
    }

    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<Fetcher> for JsValue {
    fn from(service: Fetcher) -> Self {
        JsValue::from(service.0)
    }
}

impl AsRef<wasm_bindgen::JsValue> for Fetcher {
    fn as_ref(&self) -> &wasm_bindgen::JsValue {
        &self.0
    }
}

impl From<worker_sys::Fetcher> for Fetcher {
    fn from(inner: worker_sys::Fetcher) -> Self {
        Self(inner)
    }
}