-
Notifications
You must be signed in to change notification settings - Fork 0
add WASI-HTTP interface documentation and usage example #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
43f0fa7
d941c6a
5092502
8a355bb
8c7ae35
8b5444b
662b240
ca24d37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [package] | ||
| name = "fetch" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| publish = false | ||
|
|
||
| [lib] | ||
| crate-type = ["cdylib"] | ||
|
|
||
| [dependencies] | ||
| wstd = "0.6" | ||
| anyhow = "1" | ||
|
|
||
| [package.metadata.component] | ||
| package = "component:fetch" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| ⏮️ Back to Rust [README.md](../../README.md) | ||
|
|
||
| # Fetch | ||
|
|
||
| A minimal example demonstrating outbound HTTP requests using the [WASI-HTTP](https://github.com/WebAssembly/wasi-http) interface via the [`wstd`](https://crates.io/crates/wstd) crate. | ||
|
|
||
| Unlike the other HTTP examples that use the synchronous FastEdge SDK, this example uses the WASI component model with an **async** handler and a proper HTTP client (`wstd::http::Client`). | ||
|
|
||
| ## How it works | ||
|
|
||
| The app receives an incoming request, reads the target URL from the `x-fetch-url` header, makes an outbound GET request to that URL, and streams the response back to the caller. | ||
|
|
||
| If the `x-fetch-url` header is absent, it defaults to `https://httpbin.org/get`. | ||
|
|
||
| ## Request headers | ||
|
|
||
| | Header | Required | Description | | ||
| |--------|----------|-------------| | ||
| | `x-fetch-url` | No | URL to fetch. Defaults to `https://httpbin.org/get` | | ||
|
|
||
| ## Example | ||
|
|
||
| ```bash | ||
| curl -H "x-fetch-url: https://httpbin.org/uuid" https://<your-app-domain>/ | ||
| ``` | ||
|
|
||
| ## Build | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| - Rust toolchain | ||
| - [`cargo-component`](https://github.com/bytecodealliance/cargo-component) | ||
|
|
||
| ```bash | ||
| cargo install cargo-component | ||
| ``` | ||
|
|
||
| ### Compile | ||
|
|
||
| ```bash | ||
| cargo component build --release | ||
| ``` | ||
|
|
||
| The compiled component will be at: | ||
| ``` | ||
| target/wasm32-wasip1/release/fetch.wasm | ||
| ``` | ||
|
|
||
| ## Key differences from FastEdge SDK examples | ||
|
|
||
| | | FastEdge SDK | This example (WASI-HTTP) | | ||
| |---|---|---| | ||
| | Handler | `fn main(req)` — sync | `async fn main(req)` — async | | ||
| | Macro | `#[fastedge::http]` | `#[wstd::http_server]` | | ||
| | Outbound HTTP | `fastedge::send_request(req)` | `Client::new().send(req).await` | | ||
| | Build tool | `cargo build` | `cargo component build` | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* | ||
| * Copyright 2025 G-Core Innovations SARL | ||
| */ | ||
| /* | ||
| Example app demonstrating the WASI-HTTP interface via the wstd crate. | ||
|
|
||
| The app receives an incoming HTTP request and makes an outbound HTTP request | ||
| to the URL specified in the `x-fetch-url` header (defaults to https://httpbin.org/get). | ||
|
|
||
| Build with cargo-component: | ||
| cargo component build --release | ||
| */ | ||
|
|
||
| use anyhow::anyhow; | ||
| use wstd::http::body::Body; | ||
| use wstd::http::{Client, Request, Response}; | ||
|
|
||
| #[wstd::http_server] | ||
| async fn main(request: Request<Body>) -> anyhow::Result<Response<Body>> { | ||
| let target_url = request | ||
| .headers() | ||
| .get("x-fetch-url") | ||
| .and_then(|v| v.to_str().ok()) | ||
| .unwrap_or("https://httpbin.org/get") | ||
| .to_string(); | ||
|
|
||
| println!("Fetching: {target_url}"); | ||
|
|
||
| let upstream_req = Request::get(&target_url) | ||
| .header("accept", "application/json") | ||
| .body(Body::empty()) | ||
| .map_err(|e| anyhow!("failed to build request: {e}"))?; | ||
|
|
||
| let client = Client::new(); | ||
| let response = client | ||
| .send(upstream_req) | ||
| .await | ||
| .map_err(|e| anyhow!("request failed: {e}"))?; | ||
|
|
||
| println!("Response status: {}", response.status()); | ||
|
|
||
| Ok(response) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,9 +15,14 @@ | |
| //! * **ProxyWasm API**: Compatibility layer for [ProxyWasm] environments (Envoy, etc.). | ||
| //! Available via the [`fastedge::proxywasm`](`proxywasm`) module when the `proxywasm` feature is enabled. | ||
| //! | ||
| //! * **WASI-HTTP interface**: An alternative to the FastEdge SDK using the standard [WASI-HTTP] | ||
| //! interface via the [`wstd`] crate. | ||
| //! | ||
ruslanti marked this conversation as resolved.
Show resolved
Hide resolved
ruslanti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| //! [WIT]: https://component-model.bytecodealliance.org/design/wit.html | ||
| //! [WebAssembly components]: https://component-model.bytecodealliance.org | ||
| //! [ProxyWasm]: https://github.com/proxy-wasm/spec | ||
| //! [WASI-HTTP]: https://github.com/WebAssembly/wasi-http | ||
| //! [`wstd`]: https://crates.io/crates/wstd | ||
| //! | ||
| //! ## Features | ||
| //! | ||
|
|
@@ -64,6 +69,39 @@ | |
| //! cargo build --target wasm32-wasip1 --release | ||
| //! ``` | ||
| //! | ||
| //! ### Using the WASI-HTTP Interface (async, `wstd`) | ||
| //! | ||
| //! As an alternative to the synchronous FastEdge SDK, you can use the standard [WASI-HTTP] | ||
| //! interface via the [`wstd`] crate. This enables an async handler and a proper HTTP client: | ||
| //! | ||
| //! ```no_run | ||
| //! use wstd::http::body::Body; | ||
| //! use wstd::http::{Client, Request, Response}; | ||
| //! | ||
| //! #[wstd::http_server] | ||
| //! async fn main(_request: Request<Body>) -> anyhow::Result<Response<Body>> { | ||
| //! let upstream_req = Request::get("https://api.example.com/data") | ||
| //! .header("accept", "application/json") | ||
| //! .body(Body::empty())?; | ||
| //! | ||
| //! let response = Client::new().send(upstream_req).await?; | ||
| //! Ok(response) | ||
ruslanti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| //! } | ||
|
Comment on lines
+77
to
+89
|
||
| //! ``` | ||
| //! | ||
| //! Build with [`cargo-component`] instead of `cargo build`: | ||
| //! | ||
| //! ```bash | ||
| //! cargo install cargo-component | ||
| //! cargo component build --release | ||
| //! ``` | ||
| //! | ||
| //! See the [fetch example] for a complete working app and a side-by-side comparison | ||
| //! with the FastEdge SDK approach. | ||
ruslanti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| //! | ||
| //! [`cargo-component`]: https://github.com/bytecodealliance/cargo-component | ||
| //! [fetch example]: https://github.com/G-Core/FastEdge-sdk-rust/tree/main/examples/fetch | ||
| //! | ||
| //! ## Feature Flags | ||
| //! | ||
| //! - `proxywasm` (default): Enable ProxyWasm compatibility layer | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.