Interfaces
Overview
In wasmCloud, components and providers communicate through interfaces: contracts that define the relationships between entities. These interfaces come in two kinds:
- Well-known interfaces are common standards (such as WebAssembly System Interface (WASI) APIs) or wasmCloud interfaces (core functionalities like
wasmcloud-messaging
) supported out-of-the-box by wasmCloud hosts. - Custom interfaces are user-created contracts that make it possible to extend and tailor how wasmCloud components and providers interact with one another.
In all cases, wasmCloud interfaces are defined using the interface description language WebAssembly Interface Type (WIT).
WebAssembly Interface Type (WIT)
WebAssembly Interface Type (WIT) is an open standard maintained as part of the Component Model by the W3C WebAssembly Community Group.
WIT enables WebAssembly components to define the functions they expose to external entities ("exports") and the functionalities they require ("imports") in .wit
files.
Packages, namespaces, and versions
Interfaces defined in WIT are organized into packages. Packages must include a namespace and identifier.
Optionally, WIT packages may include a version using semantic versioning.
0.2.0-draft
?The version for the example above is 0.2.0-draft
. WASI proposals move through three phases. Once a proposal reaches Phase 3, it may be included in the standard API group of WASI 0.2. The wasi-keyvalue
interface above is at Phase 2.
In wasmCloud, you will often see packages belonging to the wasmcloud
and wasi
namespaces. You may also create custom interfaces with arbitrary namespaces. Packages with different namespaces may be mixed and matched freely, and the contents of a given package may be spread across multiple files.
A common organizational pattern divides a package into:
types.wit
imports.wit
world.wit
my-interface-name.wit
An interface may also have a deps
folder holding WIT files for other WIT files used as dependencies in your interface.
For more information on organizing an interface, see Creating an interface.
Worlds
The highest-level contract in a WIT interface is called a world. A WIT world is akin to a complete description of a component, defining the imports and exports that enable the component to interact other entities. Here is a simple example of a world:
package wasmcloud:demo;
world demo {
import wasi:logging/logging;
export wasi:http/incoming-handler@0.2.0;
}
This is the top-level world for a hypothetical component that imports on the logging
interface from WASI Logging and exports (or exposes a function on) the incoming-handler
interface from WASI HTTP. This enables the component to be invoked (and respond) via HTTP and to use logging functionality.
There are often at least two worlds defined in a package. A common convention is to have an imports
world and the world components typically target.
In a wasmCloud component project, it is conventional to include a top-level WIT world at the root of a wit
folder in the project directory. At the project root, a wasmcloud.toml
configuration file tells the wash build
tool which top-level WIT world to compile into a component.
Interfaces
An interface is a collection of types and functions scoped to a package which can be used within a world. Interfaces are the only place that a type can be defined. Packages may contain multiple interfaces.
Interfaces represent the lower-level vocabulary of the contract between entities. Worlds may also refer to other worlds, which themselves may refer to interfaces or still "deeper" worlds. Here is the incoming-handler
interface imported by the world above:
/// This interface defines a handler of incoming HTTP Requests. It should
/// be exported by components which can respond to HTTP Requests.
interface incoming-handler {
use types.{incoming-request, response-outparam};
/// This function is invoked with an incoming HTTP Request, and a resource
/// `response-outparam` which provides the capability to reply with an HTTP
/// Response. The response is sent by calling the `response-outparam.set`
/// method, which allows execution to continue after the response has been
/// sent. This enables both streaming to the response body, and performing other
/// work.
///
/// The implementor of this function must write a response to the
/// `response-outparam` before returning, or else the caller will respond
/// with an error on its behalf.
handle: func(
request: incoming-request,
response-out: response-outparam
);
}
When two entities import and export respectively on the same interface (such as incoming-handler
), they can be linked so that once invoked, they interact according to the contract defined in the interface.
For more information on using WIT, see our Developer Guide page on Creating an interface.
In spite of the name, WIT isn't limited to WebAssembly: wasmCloud also uses WIT to define the interfaces used by providers and host functions written in Rust or Go. It is entirely possible, for example, to create a Rust or Go binary that uses WIT interfaces over the wRPC (WIT over RPC) protocol.
Well-known interfaces
wasmCloud supports interfaces belonging to WebAssembly System Interface (WASI) 0.2 in addition to a selection of interfaces proposed for inclusion in WASI, and interfaces belonging to the wasmCloud host.
WASI interfaces
WASI 0.2 includes these APIs, all available for use with wasmCloud 1.0:
As a security-first platform, wasmCloud provides stubbed implementations of wasi-filesystem
and wasi-sockets
that don't truly interact with the host system. For functionality that depends on these interfaces, we recommend using wasi-virt to virtualize your component. Learn more about using WASI Virt with wasmCloud on the Virtualize developer page.
Additionally, wasmCloud supports proposed WASI APIs that are in the process of implementation and standardization:
API | Versions |
---|---|
https://github.com/WebAssembly/wasi-blobstore | 0.2.0-draft |
https://github.com/WebAssembly/wasi-keyvalue | 0.2.0-draft |
https://github.com/WebAssembly/wasi-logging | [proposal] |
wasmCloud interfaces
Well-known interfaces include two APIs built specifically for wasmCloud:
API | Versions |
---|---|
wasmcloud:bus | 1.0.0 |
wasmcloud:messaging | 1.0.0 |
wasmcloud:bus
provides advanced link configuration only available in wasmCloud.wasmcloud:messaging
facilitates communication through message brokers.
Custom interfaces
WASI interfaces are ultimately common standards using WIT, but wasmCloud enables you to build custom WIT interfaces and communicate between components in the way best-suited to your requirements.
Here is an example of a greeter
interface defined in WIT:
package local:greeter-demo; // <namespace>:<package>
interface greet { // interface <name of interface>
greet: func(name: string) -> string; // a function named "greet"
}
world greeter {
export greet; // make the `greet` function available to other components/the runtime
}
While reading the spec is the best way to learn about WIT, it is also designed to be easy to understand at a glance. WASI interfaces written in WIT contain their own documentation and are useful to consult as examples.
Interface-driven development
Interface-driven development (IDD) is a development approach that focuses on defining what capabilities components require before the specifics of how you will meet those needs.
Systems developed using IDD—especially distributed systems—are loosely coupled, robust, and maintainable.
Keep reading
Continue to learn more about how the wasmCloud host, or...
- Explore the Developer Guide to learn more about creating your own interfaces.