client.rs 2.9 KB
use js_sys::JsString;
use mogwai::prelude::*;
use wasm_bindgen::prelude::*;
use web_sys::{Window, window, Response, Request, RequestInit, RequestMode, Headers};
use super::error::*;

use std::result::Result as StdResult;

#[derive(Debug, Clone)]
pub(crate) struct Client {
    window :Window,
}

type ReqGetter = fn(&str, &RequestInit) -> StdResult<Request, JsValue>;

const REQUEST :ReqGetter = Request::new_with_str_and_init;

impl Client {
    pub fn new() -> Result<Self> {
        const WINDOW_ERROR :&str = "Unable to get window instance";

        Ok(Self { window: window()
                        . ok_or(Error::from(WINDOW_ERROR))? })
    }

    pub async fn get(&self, url :&str) -> Result<(Response, String)> {
        let mut init = RequestInit::new();
        let request = REQUEST( url
                             , init . method("GET")
                                    . mode(RequestMode::Cors) )?;

        request . headers()
                . set("Accept", "application/json")?;

        let response = JsFuture::from( self.window
                                     . fetch_with_request(&request) )
                     . await?
                     . dyn_into::<Response>()?;

        let data = JsFuture::from(response.text()?)
                 . await?
                 . dyn_into::<JsString>()?;

        Ok((response, String::from(data)))
    }

    pub async fn put(&self, url :&str, data :&str) -> Result<Response> {
        let mut init = RequestInit::new();
        let request = REQUEST( url
                             , init . method("PUT")
                                    . mode(RequestMode::Cors)
                                    . body(Some(&data.into())) )?;

        request . headers()
                . set("Content-Type", "application/json")?;

        let response = JsFuture::from( self.window
                                     . fetch_with_request(&request))
                     . await?
                     . dyn_into::<Response>()?;

        Ok(response)
    }

    pub async fn post_stream( &self
                            , url       :&str
                            , mime_type :&str
                            , length    :usize
                            , data      :&JsValue ) -> Result<Response> {
        let headers = Headers::new()?;
        headers.set("Content-Type", mime_type)?;
        headers.set("Content-Length", &format!("{}", length))?;

        let mut init = RequestInit::new();
        let request = REQUEST( url
                             , init . method("POST")
                                    . mode(RequestMode::Cors)
                                    . headers(&headers.into())
                                    . body(Some(data)) )?;

        let response = JsFuture::from( self.window
                                     . fetch_with_request(&request))
                     . await?
                     . dyn_into::<Response>()?;

        Ok(response)
    }
}