Making HTTP Calls on FastEdge

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)
}
Note: 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();
    }
}
Tip: The raw proxy-wasm approach lets you make HTTP calls while the client request is paused — perfect for authentication checks, rate limiting, or content aggregation at the edge.

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

Caveat: HTTP calls from FastEdge use the proxy-wasm ABI and are subject to the edge provider's timeout and resource limits. Timeouts default to 5 seconds on most plans.