Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 105 additions & 19 deletions plugins/gcore-fastedge/skills/fastedge-docs/reference/cdn-apps-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
sources:
- id: fastedge-sdk-rust
ref: main
commit: 6347a7c2fda0d03e66f1214db5eec041c16801b7
updated: 2026-08-20
commit: 6eedcca9d5c0ddd4ff79ca475965393891da2d75
updated: 2026-09-22
-->

# FastEdge Rust SDK — CDN Apps (Proxy-Wasm)
Expand Down Expand Up @@ -46,7 +46,7 @@ proxy-wasm = "0.2"
log = "0.4"
```

**Tier 2 — CDN app with FastEdge host services** (KV, secrets, dictionary):
**Tier 2 — CDN app with FastEdge host services** (KV, cache, secrets, dictionary):

```toml
[package]
Expand Down Expand Up @@ -195,12 +195,12 @@ impl HttpContext for HelloWorld {

## Lifecycle Callbacks

| Callback | Phase | Description |
| ----------------------------------------------------------------- | ---------------- | --------------------------------------------------- |
| `on_http_request_headers(num_headers: usize, end_of_stream: bool) -> Action` | Request headers | Inspect or modify request headers before forwarding |
| `on_http_request_body(body_size: usize, end_of_stream: bool) -> Action` | Request body | Inspect or modify request body before forwarding |
| `on_http_response_headers(num_headers: usize, end_of_stream: bool) -> Action` | Response headers | Inspect or modify response headers from origin |
| `on_http_response_body(body_size: usize, end_of_stream: bool) -> Action` | Response body | Inspect or modify response body from origin |
| Callback | Phase | Description |
| ----------------------------------------------------------------------------------------------- | ---------------- | --------------------------------------------------- |
| `on_http_request_headers(num_headers: usize, end_of_stream: bool) -> Action` | Request headers | Inspect or modify request headers before forwarding |
| `on_http_request_body(body_size: usize, end_of_stream: bool) -> Action` | Request body | Inspect or modify request body before forwarding |
| `on_http_response_headers(num_headers: usize, end_of_stream: bool) -> Action` | Response headers | Inspect or modify response headers from origin |
| `on_http_response_body(body_size: usize, end_of_stream: bool) -> Action` | Response body | Inspect or modify response body from origin |

All callbacks have default no-op implementations. Override only the phases your app needs to process.

Expand Down Expand Up @@ -508,6 +508,91 @@ impl HttpContext for RateLimitFilter {
}
```

### Cache (`fastedge::proxywasm::cache`)

Provides ephemeral cache storage, implemented by the host. Unlike `key_value::Store`, cache operations are not scoped to a named store or handle — every function is a free function keyed directly, and every entry is scoped to the calling application.

```rust,ignore
pub fn get(key: &str) -> Result<Option<Vec<u8>>, Error>
pub fn set(key: &str, value: &[u8], ttl_ms: Option<u64>) -> Result<(), Error>
pub fn delete(key: &str) -> Result<(), Error>
pub fn exists(key: &str) -> Result<bool, Error>
pub fn incr(key: &str, delta: i64) -> Result<i64, Error>
pub fn expire(key: &str, ttl_ms: u64) -> Result<bool, Error>
pub fn purge() -> Result<u64, Error>
pub fn purge_prefix(prefix: &str) -> Result<u64, Error>
```

| Function | Return Type | Description |
| ---------------------------------------------------- | -------------------------------- | ---------------------------------------------------------------------------- |
| `get(key: &str)` | `Result<Option<Vec<u8>>, Error>` | Get the value for a key; `None` if the key does not exist |
| `set(key: &str, value: &[u8], ttl_ms: Option<u64>)` | `Result<(), Error>` | Set a value with an optional expiry; `None` means no expiry |
| `delete(key: &str)` | `Result<(), Error>` | Delete a key; a no-op if the key does not exist |
| `exists(key: &str)` | `Result<bool, Error>` | Test whether a key exists |
| `incr(key: &str, delta: i64)` | `Result<i64, Error>` | Atomically increment (or decrement) an integer value; returns the new value |
| `expire(key: &str, ttl_ms: u64)` | `Result<bool, Error>` | Set or update a key's expiry; `false` if the key does not exist |
| `purge()` | `Result<u64, Error>` | Delete all cache entries owned by the calling application |
| `purge_prefix(prefix: &str)` | `Result<u64, Error>` | Delete all cache entries whose key begins with `prefix` |

`purge()` and `purge_prefix()` both return the number of keys that were deleted.

#### `Error`

```rust,ignore
pub enum Error {
AccessDenied,
InternalError,
Other(String),
}
```

| Variant | Description |
| --------------- | ----------------------------------------------------------- |
| `AccessDenied` | The application does not have access to the specified cache |
| `InternalError` | An unexpected internal error occurred |
| `Other(String)` | An implementation-specific error (e.g., I/O failure) |

#### Example — cache a computed value in the response headers phase

```rust,no_run
use fastedge::proxywasm::cache;
use proxy_wasm::traits::*;
use proxy_wasm::types::*;

proxy_wasm::main! {{
proxy_wasm::set_log_level(LogLevel::Trace);
proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(CacheRoot) });
}}

struct CacheRoot;
impl Context for CacheRoot {}
impl RootContext for CacheRoot {
fn get_type(&self) -> Option<ContextType> { Some(ContextType::HttpContext) }
fn create_http_context(&self, _: u32) -> Option<Box<dyn HttpContext>> {
Some(Box::new(CacheFilter))
}
}

struct CacheFilter;
impl Context for CacheFilter {}

impl HttpContext for CacheFilter {
fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {
match cache::get("key-3338664") {
Ok(Some(_cached)) => {
// reuse the cached value
}
Ok(None) => {
// store the value for 5 minutes
let _ = cache::set("key-3338664", b"value", Some(300_000));
}
Err(_) => {}
}
Action::Continue
}
}
```

### Secret Management (`fastedge::proxywasm::secret`)

Provides access to encrypted secrets stored in the FastEdge platform.
Expand Down Expand Up @@ -733,16 +818,17 @@ The `log` crate macros (`info!`, `warn!`, `error!`, etc.) work when `proxy_wasm:

## API Comparison: HTTP vs CDN

| Service | HTTP Apps (Component Model) | CDN Apps (ProxyWasm) |
| ------------- | ------------------------------------------------------------------- | -------------------------------------------------------- |
| Key-Value | `fastedge::key_value::Store` | `fastedge::proxywasm::key_value::Store` |
| Secrets | `fastedge::secret::get` | `fastedge::proxywasm::secret::get` |
| Dictionary | `fastedge::dictionary::get` | `fastedge::proxywasm::dictionary::get` |
| Diagnostics | `fastedge::utils::set_user_diag` | `fastedge::proxywasm::utils::set_user_diag` |
| Error types | Typed `Error` enums | `u32` status codes (secret) or typed `Error` (key_value) |
| Cargo feature | None required | `features = ["proxywasm"]` |
| Build target | `wasm32-wasip1` (basic) / `wasm32-wasip2` (wstd) | `wasm32-wasip1` |
| Handler | `#[wstd::http_server]` (recommended) / `#[fastedge::http]` (basic) | `proxy_wasm::main!` + traits |
| Service | HTTP Apps (Component Model) | CDN Apps (ProxyWasm) |
| ------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------- |
| Key-Value | `fastedge::key_value::Store` | `fastedge::proxywasm::key_value::Store` |
| Cache | `fastedge::cache` | `fastedge::proxywasm::cache` |
| Secrets | `fastedge::secret::get` | `fastedge::proxywasm::secret::get` |
| Dictionary | `fastedge::dictionary::get` | `fastedge::proxywasm::dictionary::get` |
| Diagnostics | `fastedge::utils::set_user_diag` | `fastedge::proxywasm::utils::set_user_diag` |
| Error types | Typed `Error` enums | `u32` status codes (secret) or typed `Error` (key_value, cache) |
| Cargo feature | None required | `features = ["proxywasm"]` |
| Build target | `wasm32-wasip1` (basic) / `wasm32-wasip2` (wstd) | `wasm32-wasip1` |
| Handler | `#[wstd::http_server]` (recommended) / `#[fastedge::http]` (basic) | `proxy_wasm::main!` + traits |

## See Also

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
sources:
- id: fastedge-sdk-rust
ref: main
commit: 6347a7c2fda0d03e66f1214db5eec041c16801b7
updated: 2026-08-20
commit: 6eedcca9d5c0ddd4ff79ca475965393891da2d75
updated: 2026-09-22
-->

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
sources:
- id: fastedge-sdk-rust
ref: main
commit: 6347a7c2fda0d03e66f1214db5eec041c16801b7
updated: 2026-08-20
commit: 6eedcca9d5c0ddd4ff79ca475965393891da2d75
updated: 2026-09-22
-->

# API Key Validation — CDN (Rust)
Expand Down Expand Up @@ -159,120 +159,3 @@ return Action::Pause;
- Host services reference — secrets API (`fastedge::proxywasm::secret`) and other CDN host services
- CDN apps reference — proxy-wasm app structure, `RootContext`/`HttpContext` setup, `Action` enum, and request property encodings
- SDK API reference — Rust CDN SDK traits and types

## Source Material

### FILE: examples/cdn/api_key/src/lib.rs

```rust
/*
* Copyright 2025 G-Core Innovations SARL
*/
/*
Example CDN app demonstrating API key validation.

Validates requests using an X-API-Key header checked against a stored
secret. Simpler alternative to JWT when token expiry and claims are
not needed.

Required configuration:
- Secret: API_KEY
*/

use fastedge::proxywasm::secret;
use proxy_wasm::traits::*;
use proxy_wasm::types::*;

proxy_wasm::main! {{
proxy_wasm::set_log_level(LogLevel::Info);
proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(ApiKeyRoot) });
}}

struct ApiKeyRoot;

impl Context for ApiKeyRoot {}

impl RootContext for ApiKeyRoot {
fn get_type(&self) -> Option<ContextType> {
Some(ContextType::HttpContext)
}

fn create_http_context(&self, _: u32) -> Option<Box<dyn HttpContext>> {
Some(Box::new(ApiKeyContext))
}
}

struct ApiKeyContext;

impl Context for ApiKeyContext {}

impl HttpContext for ApiKeyContext {
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
let expected_key = match secret::get("API_KEY") {
Ok(Some(bytes)) => match String::from_utf8(bytes) {
Ok(s) if !s.is_empty() => s,
_ => {
self.send_http_response(500, vec![], Some(b"App misconfigured"));
return Action::Pause;
}
},
_ => {
self.send_http_response(500, vec![], Some(b"App misconfigured"));
return Action::Pause;
}
};

let provided_key = match self.get_http_request_header("X-API-Key") {
Some(k) if !k.is_empty() => k,
_ => {
self.send_http_response(
401,
vec![("WWW-Authenticate", "API-Key")],
Some(b"Missing X-API-Key header"),
);
return Action::Pause;
}
};

if provided_key != expected_key {
println!("API key validation failed");
self.send_http_response(403, vec![], Some(b"Invalid API key"));
return Action::Pause;
}

// Strip the API key header before forwarding to upstream
self.set_http_request_header("X-API-Key", None);

println!("API key validated successfully");
Action::Continue
}
}
```

### FILE: examples/cdn/api_key/Cargo.toml

```toml
[workspace]

[package]
name = "api_key"
version = "0.1.0"
edition = "2024"

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

[dependencies]
proxy-wasm = "0.2"
fastedge = { version = "0.4", features = ["proxywasm"] }
```

### FILE: examples/cdn/api_key/README.md

```
[← Back to examples](../../README.md)

# API Key (CDN)

Validates requests using an `X-API-Key` header checked against a stored secret. Returns 401 if missing, 403 if invalid, and strips the header before forwarding to upstream.
```
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
sources:
- id: fastedge-sdk-rust
ref: main
commit: 6347a7c2fda0d03e66f1214db5eec041c16801b7
updated: 2026-08-20
commit: 6eedcca9d5c0ddd4ff79ca475965393891da2d75
updated: 2026-09-22
-->

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
sources:
- id: fastedge-sdk-rust
ref: main
commit: 6347a7c2fda0d03e66f1214db5eec041c16801b7
updated: 2026-08-20
commit: 6eedcca9d5c0ddd4ff79ca475965393891da2d75
updated: 2026-09-22
-->

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
sources:
- id: fastedge-sdk-rust
ref: main
commit: 6347a7c2fda0d03e66f1214db5eec041c16801b7
updated: 2026-08-20
commit: 6eedcca9d5c0ddd4ff79ca475965393891da2d75
updated: 2026-09-22
-->

---
Expand Down
Loading
Loading