4

I am developing a NODE JS package using Rust and wasm-pack to compile, and I need to make HTTP requests in my code. I tried to use reqwest library, so everything works fine in the test but I get an error in packing.

#![allow(non_snake_case)]

use reqwest;
use wasm_bindgen::prelude::*;

// function
#[wasm_bindgen]
pub fn makeGetRequest(url: &str) -> String {
    let mut resp = reqwest::get(url).unwrap();
    resp.text().unwrap()
}

// test
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_makeGetRequest() {
        let url = "https://stackoverflow.com/";
        let body = makeGetRequest(url);
        assert!(body.len() > 0);
    }
}

Configuration Cargo.toml:

...

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
reqwest = "0.9"

I pack the project with the command:

wasm-pack build --release --target nodejs

And I get the error:

...
error: could not compile `net2`

I found that it looks like net2 is not supported in wasm-pack, so perhaps I cannot use reqwest in my case: wasm-pack build report error: could not compile `net2`

Is there a way to make synchronous HTTP requests that can be packed with wasm-pack successfully?

Fomalhaut
  • 8,590
  • 8
  • 51
  • 95
  • 1
    If wasm running in a browser the request has to pas through via the host https://stackoverflow.com/a/52104044/5396835 – Jonas Bojesen Feb 27 '21 at 18:53

3 Answers3

4

It won't work as easily as you'd expect: WASM bytecode is executed in a protected environment without any access to OS features like disk, network, conventional random generators and any other type of I/O. Consequently, the moment you compile any Rust code using such features into Wasm, it won't work.

Unfortunately your code (e.g. file access) usually even compiles silently and then fails in mysterious ways during runtime. This is not what you got used to using Rust and a major drawback of the current Wasm Rust stack.

To access OS features, you'll need WASI (Wasm System Interface) as an extension. To enable Wasi in NodeJs, you can use something like WasmerJs, see e.g. this article providing a short summary to do so.

Zólyomi István
  • 2,401
  • 17
  • 28
  • 1
    IIUC, you don't *need* WASI to access host features. That just makes the glue code smaller. It just a question of whether wasm-pack produces the glue code to coordinate a request with the host runtime of the wasm module, and whether the runtime actually has the capabilities that you're trying to use. – joe Mar 26 '22 at 03:10
0

Reqwest version 0.11 compiles to wasm.

# Cargo.toml
[dependencies]
reqwest = { version = "0.11" }

Here is an async example:

async fn fetch(url: &str) -> String {
    let client = reqwest::Client::new();
    let resp = client.get(url).send().await.unwrap();
    resp.text().await.unwrap()
}

You can run it from a non async function but not get the result as return because spawn_local returns ().

mod tests {
    use wasm_bindgen_futures::spawn_local;
    use wasm_bindgen_test::*;
    
    wasm_bindgen_test_configure!(run_in_browser);
    
    async fn fetch(url: &str) -> String {
        let client = reqwest::Client::new();
        let resp = client.get(url).send().await.unwrap();
        resp.text().await.unwrap()
    }
    
    #[wasm_bindgen_test]
    fn fetch_test() {
        spawn_local(async move {
            let result = fetch("https://ifconfig.me/ip").await;
            wasm_bindgen_test::console_log!("Your IP: {}", result);
        });
    }
}

Test it with wasm-pack test --chrome.

If you have tokio in your project, disable it on wasm build, because it uses net2.

# Cargo.toml
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.0", features = ["full"] }
chriamue
  • 961
  • 5
  • 15
  • 1
    Still an error on `wasm-pack` stage: "could not find `blocking` in `reqwest`". But on test it works fine. – Fomalhaut Apr 09 '23 at 09:07
0

Since you're asking about making Http request in wasm_bindgen, do you really need to use reqwest since there is an example on wasm_bindgens docs on how to use Fetch from within a rust wasm module, https://rustwasm.github.io/docs/wasm-bindgen/examples/fetch.html

I've tried it right now and it works in a browser, NodeJS 18 does ship with fetch would it work for your usecase? https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#browser_compatibility

FYI full example from wasm-bindgen: https://github.com/rustwasm/wasm-bindgen/tree/main/examples/fetch#readme

Zablon
  • 117
  • 1
  • 4