FastEdge isn't just for responding to requests — you can also make outbound HTTP calls from your edge worker. This is useful for fetching data from upstream APIs, aggregating content, or acting as a proxy.
The fastedge crate approach
Using the fastedge crate's http_client module, you can send any HTTP request and get back a response — all from within your WASM handler:
use fastedge::{
body::Body,
http::{Request, StatusCode},
http_client,
};
#[fastedge::http]
pub fn main(_req: Request<Body>) -> Result<Response<Body>, Error> {
// Build an outbound request
let upstream = Request::builder()
.method("GET")
.uri("https://httpbin.org/ip")
.header("User-Agent", "fastedge")
.body(Body::empty())
.unwrap();
// Send it from the edge
let resp = http_client::send_request(upstream)?;
// Forward the upstream response
Ok(resp)
}
send_request is synchronous from the handler's perspective — it blocks the WASM context until the remote responds, so keep timeouts in mind.
Raw proxy-wasm approach
For more advanced control (e.g., intercepting the client request and making an async HTTP call before continuing), you can drop down to raw proxy_wasm:
use proxy_wasm::traits::*;
use std::time::Duration;
struct MyRoot;
impl Context for MyRoot {}
impl RootContext for MyRoot {
fn create_http_context(&self, id: u32) -> Option<Box<dyn HttpContext>> {
Some(Box::new(MyHttp { state: 0 }))
}
fn get_type(&self) -> Option<ContextType> {
Some(ContextType::HttpContext)
}
}
In on_http_request_headers, you call self.dispatch_http_call(...) and return Action::Pause to wait for the response. The response arrives in on_http_call_response, where you can inspect headers, read the body, and then call self.resume_http_request() to let the original request continue.
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
match self.dispatch_http_call(
"httpbin.org",
vec![
(":scheme", "https"),
(":authority", "httpbin.org"),
(":path", "/ip"),
],
None, // no body
vec![], // no trailers
Duration::from_secs(5),
) {
Ok(token) => {
println!("Dispatched call token: {token}");
Action::Pause
}
Err(status) => {
self.send_http_response(500, vec![], b"dispatch failed");
Action::Pause
}
}
}
pub fn on_http_call_response(&mut self, token_id: u32, num_headers: usize, body_size: usize, _: usize) {
if num_headers > 0 {
let body = self.get_http_call_response_body(0, body_size);
println!("Response body: {:?}", body);
self.state = 1;
self.resume_http_request();
} else {
self.reset_http_request();
}
}
When to use which
Use fastedge::http_client::send_request when you just need to fetch something and return it — it's simpler and works within the familiar Request/Response model. Use the raw proxy-wasm approach when you need to intercept, augment, or gate a client request with data from an external source.
Full example
Check out the complete working example on GitHub:
github.com/G-Core/FastEdge-sdk-rust/examples/cdn/http_call