Rust wasm yew sending requests

137 Views Asked by At

I'm working with yew and I found a problem. I think I know what is causing it but I couldn't find any help so I got here. The code is just an example from yew futures and it works on some url's and not on others. I have noticed one thing, when I curl(on zsh) for example www.google.com I get a "%" sign on the end and when I curl the provided links in the example I don't. Yes I know that is the wrong configuration of zsh but it is the only thing I could find so I might as well tell you about it.

Here is the code(it's the same as the example in yew futures but with changed link)

use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};

use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use yew::{html, Component, Context, Html};


const SOME_URL: &str = "https://google.com";
const CORRECT_URL: &str = "https://raw.githubusercontent.com/yewstack/yew/master/README.md";

/// Something wrong has occurred while fetching an external resource.
#[derive(Debug, Clone, PartialEq)]
pub struct FetchError {
    err: JsValue,
}
impl Display for FetchError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Debug::fmt(&self.err, f)
    }
}
impl Error for FetchError {}

impl From<JsValue> for FetchError {
    fn from(value: JsValue) -> Self {
        Self { err: value }
    }
}

/// The possible states a fetch request can be in.
pub enum FetchState<T> {
    NotFetching,
    Fetching,
    Success(T),
    Failed(FetchError),
}

/// Fetches markdown from Yew's README.md.
///
/// Consult the following for an example of the fetch api by the team behind web_sys:
/// https://rustwasm.github.io/wasm-bindgen/examples/fetch.html
async fn fetch_markdown(url: &'static str) -> Result<String, FetchError> {
    let mut opts = RequestInit::new();
    opts.method("GET");
    opts.mode(RequestMode::Cors);

    let request = Request::new_with_str_and_init(url, &opts)?;

    let window = gloo::utils::window();
    let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
    let resp: Response = resp_value.dyn_into().unwrap();

    let text = JsFuture::from(resp.text()?).await?;
    Ok(text.as_string().unwrap())
}

enum Msg {
    SetMarkdownFetchState(FetchState<String>),
    GetResponse,
    GetError,
}
struct App {
    markdown: FetchState<String>,
}

impl Component for App {
    type Message = Msg;
    type Properties = ();

    fn create(_ctx: &Context<Self>) -> Self {
        Self {
            markdown: FetchState::NotFetching,
        }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            Msg::SetMarkdownFetchState(fetch_state) => {
                self.markdown = fetch_state;
                true
            }
            Msg::GetResponse => {
                ctx.link().send_future(async {
                    match fetch_markdown(CORRECT_URL).await {
                        Ok(md) => Msg::SetMarkdownFetchState(FetchState::Success(md)),
                        Err(err) => Msg::SetMarkdownFetchState(FetchState::Failed(err)),
                    }
                });
                ctx.link()
                    .send_message(Msg::SetMarkdownFetchState(FetchState::Fetching));
                false
            }
            Msg::GetError => {
                ctx.link().send_future(async {
                    match fetch_markdown(SOME_URL).await {
                        Ok(md) => Msg::SetMarkdownFetchState(FetchState::Success(md)),
                        Err(err) => Msg::SetMarkdownFetchState(FetchState::Failed(err)),
                    }
                });
                ctx.link()
                    .send_message(Msg::SetMarkdownFetchState(FetchState::Fetching));
                false
            }

        }
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        match &self.markdown {
            FetchState::NotFetching => html! {
                <>
                    <button onclick={ctx.link().callback(|_| Msg::GetResponse)}>
                        { "Get Response" }
                    </button><br/>
                    <button onclick={ctx.link().callback(|_| Msg::GetError)}>
                        { "Get response using some random url" }
                    </button><br/>
                </>
            },
            FetchState::Fetching => html! { "Fetching" },
            FetchState::Success(data) => html! { data },
            FetchState::Failed(err) => html! { err },
        }
    }
}

fn main() {
    yew::Renderer::<App>::new().render();
}

and here is the error when I try to fetch from google.com

JsValue(TypeError: Failed to fetch TypeError: Failed to fetch at imports.wbg.__wbg_fetch_336b6f0cb426b46e (http://localhost:3000/futures-36637e7fd4a2244d.js:408:37) at web_sys::features::gen_Window::Window::fetch_with_request::he024cfe53b8c9d8a (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[2243]:0xe22e4) at futures::fetch_markdown::{{closure}}::h71cb4aef60ce88ea (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[111]:0x29f83) at <futures::App as yew::html::component::Component>::update::{{closure}}::h164496c17a68c16a (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[206]:0x4c72a) at yew::html::component::scope::Scope<COMP>::send_future::{{closure}}::hf679213ffb53e5f4 (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[169]:0x4153d) at wasm_bindgen_futures::task::singlethread::Task::run::hdfe513013dde3df2 (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[457]:0x7a75f) at wasm_bindgen_futures::queue::QueueState::run_all::hfc7f0f72228a8044 (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[313]:0x645fb) at wasm_bindgen_futures::queue::Queue::new::{{closure}}::h192c6b50a18495ff (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[2044]:0xdcb01) at <dyn core::ops::function::FnMut<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::h13d0e47eecdf6ae9 (http://localhost:3000/futures-36637e7fd4a2244d_bg.wasm:wasm-function[1395]:0xc367d) at __wbg_adapter_21 (http://localhost:3000/futures-36637e7fd4a2244d.js:245:10))

I have tried rewriting it with different libraries and I tried to create an api endpoint in rust that would send newline(I think) at the end but I couldn't do it.

0

There are 0 best solutions below