diff --git a/Cargo.lock b/Cargo.lock index ef765ce..a81100d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,6 +341,13 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "readonly" +version = "0.1.0" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "semver" version = "1.0.28" diff --git a/README.md b/README.md index f4b6065..67d559e 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ make components ### Components - [`http-client`](./components/http-client/) +- [`readonly`](./components/readonly/) ## Community diff --git a/components/http-client/README.md b/components/http-client/README.md index 2dcab4f..ac987a4 100644 --- a/components/http-client/README.md +++ b/components/http-client/README.md @@ -20,4 +20,4 @@ A higher-level HTTP client that delegates to wasi:http/client. ## The `http-client` World - exports `componentized:http/client` -- imports `wasi:http/client@0.3.1` +- imports `wasi:http/client@0.3` diff --git a/components/readonly/Cargo.toml b/components/readonly/Cargo.toml new file mode 100644 index 0000000..b37a951 --- /dev/null +++ b/components/readonly/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "readonly" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wit-bindgen = { workspace = true, features = ["async-spawn"] } diff --git a/components/readonly/README.md b/components/readonly/README.md new file mode 100644 index 0000000..ce4cd5c --- /dev/null +++ b/components/readonly/README.md @@ -0,0 +1,8 @@ +# `readonly` + +Restricts http methods to `get`, `head`, `query` and `options`, otherwise returns `http-request-method-invalid` error code. + +## The `readonly` World + +- exports `wasi:http/client@0.3` +- imports `wasi:http/client@0.3` diff --git a/components/readonly/src/lib.rs b/components/readonly/src/lib.rs new file mode 100644 index 0000000..daca7a9 --- /dev/null +++ b/components/readonly/src/lib.rs @@ -0,0 +1,49 @@ +#![no_std] + +use crate::{ + exports::wasi::http::client::{ErrorCode, Guest, Request, Response}, + wasi::http::{client, types::Method}, +}; + +struct ReadOnlyClient; + +impl ReadOnlyClient { + fn allowed_method(method: Method) -> bool { + let method = match method { + Method::Get => "get", + Method::Head => "head", + Method::Post => "post", + Method::Put => "put", + Method::Delete => "delete", + Method::Connect => "connect", + Method::Options => "options", + Method::Trace => "trace", + Method::Patch => "patch", + Method::Other(method) => &method.to_lowercase(), + }; + match method { + "get" | "head" | "query" | "options" => true, + _ => false, + } + } +} + +impl Guest for ReadOnlyClient { + #[doc = "/ This function may be used to either send an outgoing request over the"] + #[doc = "/ network or to forward it to another component."] + #[allow(async_fn_in_trait)] + async fn send(request: Request) -> Result { + match Self::allowed_method(request.get_method()) { + true => client::send(request).await, + false => Err(ErrorCode::HttpRequestMethodInvalid), + } + } +} + +export!(ReadOnlyClient); + +wit_bindgen::generate!({ + path: "../wit", + world: "client", + generate_all, +}); diff --git a/components/wit/worlds.wit b/components/wit/worlds.wit index 18cb318..02f495f 100644 --- a/components/wit/worlds.wit +++ b/components/wit/worlds.wit @@ -4,3 +4,8 @@ world http-client { import wasi:http/client@0.3.0; export componentized:http/client@0.1.0-dev; } + +world client { + import wasi:http/client@0.3.0; + export wasi:http/client@0.3.0; +}