A Rust client for Apache OpenWhisk needs to translate resource operations into authenticated HTTP requests and turn the responses into values application code can use. Supporting more than one execution environment adds another concern: the same resource API may need different HTTP implementations.

I built the OpenWhisk Rust client from its first API operations into a library with separate resource and transport interfaces. The design question became especially concrete when I added Wasm support: actions, triggers, rules, and namespaces needed to keep their meaning while the code executing their HTTP requests changed.

Organize the API around OpenWhisk resources

The initial library introduced basic operations, followed by action invocation and support for rules and namespaces.

I then separated the code into resource APIs and client modules. Actions, triggers, rules, and namespaces expose the operations relevant to each resource. Shared context carries connection and authentication settings, while a service interface handles request construction and execution. This division is visible in the early library restructuring.

The architectural purpose is to keep resource behavior independent of a particular HTTP client. An action invocation should retain the same API meaning when its request is executed in a different environment.

Return failures to the caller

The error-handling work revised request construction, execution, and response conversion to return recoverable failures through Result in the affected paths.

That distinction matters to applications embedding the library. A failed request or an unexpected response needs to reach the caller, which can decide whether to report it, stop the operation, or attempt recovery. The library provides the failure information; the application owns the policy.

This work included response-model adjustments as well as error propagation. The shape of an API response and the way a failure is represented both determine whether callers can handle the result correctly.

Separate native and Wasm HTTP execution

I added a Wasmtime-oriented client, followed by Wasm client refinements.

The native implementation uses a blocking reqwest client. The Wasm implementation uses the runtime HTTP interface provided by wasi-experimental-http. Both implement the service boundary used by the resource APIs, although they construct and execute requests differently.

The Wasm support is tied to that runtime interface. It demonstrates the shared API operating over a second transport implementation; it does not imply support for every browser or Wasm runtime.

Test the request and response boundary

The later test work introduced mock HTTP servers and helpers for resource responses. Tests exercise actions, namespaces, rules, and triggers, alongside corrections to rule operations and status handling.

Testing at that boundary makes the resource mapping concrete: the request sent, the response received, and the value exposed to the caller can be examined together. It also allows those behaviors to be checked against controlled responses.

What shipped

The merged implementation includes resource APIs, shared connection context, native and Wasm HTTP clients, recoverable error handling in revised request paths, tests, and usage documentation.

The central design decision was the separation between OpenWhisk resource semantics and HTTP execution. That boundary allowed the library to grow from its first operations into multiple client implementations without requiring each resource to own the transport details.

Explore my OpenWhisk client repository · Upstream implementation · Back to projects