我正在开发一个 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请求?
它不会像您期望的那样轻松工作:WASM 字节码在受保护的环境中执行,无需访问磁盘、网络、传统随机生成器和任何其他类型的 I/O 等操作系统功能。因此,当您将使用此类功能的任何 Rust 代码编译到 Wasm 中时,它将无法工作。
不幸的是,您的代码(例如文件访问)通常甚至会静默编译,然后在运行时以神秘的方式失败。这不是您习惯使用 Rust 的情况,也是当前 Wasm Rust 堆栈的主要缺点。
要访问操作系统功能,您需要 WASI(Wasm 系统接口) 作为扩展。要在 NodeJs 中启用 Wasi,您可以使用 WasmerJs 之类的东西,请参阅例如本文为此提供了简短的摘要。
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"] }
既然你问的是在 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