如何在 Rust 的 wasm_bindgen 函数中发出 HTTP 请求?

问题描述 投票:0回答:3

我正在开发一个 NODE JS 包,使用 Rust 和

wasm-pack
进行编译,我需要在我的代码中发出 HTTP 请求。我尝试使用
reqwest
库,所以在测试中一切正常,但在打包时出现错误。

#![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);
    }
}

配置

Cargo.toml

...

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

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

我使用以下命令打包项目:

wasm-pack build --release --target nodejs

我收到错误:

...
error: could not compile `net2`

我发现

net2
wasm-pack
中不受支持,所以在我的情况下我可能无法使用
reqwest
wasm-pack构建报告错误:无法编译`net2`

有没有办法发出可以成功打包

wasm-pack
的同步HTTP请求?

node.js rust webassembly wasm-bindgen reqwest
3个回答
4
投票

它不会像您期望的那样轻松工作:WASM 字节码在受保护的环境中执行,无需访问磁盘、网络、传统随机生成器和任何其他类型的 I/O 等操作系统功能。因此,当您将使用此类功能的任何 Rust 代码编译到 Wasm 中时,它将无法工作。

不幸的是,您的代码(例如文件访问)通常甚至会静默编译,然后在运行时以神秘的方式失败。这不是您习惯使用 Rust 的情况,也是当前 Wasm Rust 堆栈的主要缺点。

要访问操作系统功能,您需要 WASI(Wasm 系统接口) 作为扩展。要在 NodeJs 中启用 Wasi,您可以使用 WasmerJs 之类的东西,请参阅例如本文为此提供了简短的摘要。


0
投票

Reqwest 0.11 版本编译为 wasm。

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

这是一个异步示例:

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

您可以从非异步函数运行它,但无法获得返回结果,因为spawn_local返回()。

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);
        });
    }
}

wasm-pack test --chrome
进行测试。

如果您的项目中有 tokio,请在 wasm build 上禁用它,因为它使用 net2。

# Cargo.toml
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.0", features = ["full"] }

0
投票

既然你问的是在 wasm_bindgen 中发出 Http 请求,你真的需要使用

reqwest
因为 wasm_bindgens 文档上有一个关于如何在 rust wasm 模块中使用
Fetch
的示例,https://rustwasm .github.io/docs/wasm-bindgen/examples/fetch.html

我现在已经尝试过了,它可以在浏览器中运行,NodeJS 18 确实附带了 fetch,它适合您的用例吗? https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#browser_compatibility

仅供参考 wasm-bindgen 的完整示例:https://github.com/rustwasm/wasm-bindgen/tree/main/examples/fetch#readme

© www.soinside.com 2019 - 2024. All rights reserved.