Skip to main content
Version: 1.x

Create

We provide example templates for creating components in Rust, TinyGo, Python, and TypeScript. You can use these templates to create a new component project, or you can use them as a reference for creating your own component from scratch. As other languages are updated to use the same component APIs that wasmtime uses, we will add templates for those languages as well.

Creating the scaffold for a new component in Rust is easy. We will create a component that accepts an HTTP request and responds with "Hello from Rust!". To create your new component project, change to the directory where you want the project to be created, and enter the command below. The first term on the command (hello) is the project name. If you choose a different project name, the name of the subdirectory and some symbols in the generated code will be different from the example code in this guide.

bash
wash new component hello --template-name hello-world-rust

Let's change into the newly-created folder hello and take a look at the generated project. The file src/lib.rs includes a wit-bindgen generate macro, an imports section, a struct HttpServer, and an impl block that implements the Guest trait for the component struct. Let's walk through these sections in detail.

rust
wit_bindgen::generate!();

This shows us that we're using a core wasmCloud package called wit-bindgen to generate the types and bindings for our component. This is automatically done from the wit/world.wit file, any changes to imports or exports will update automatically on the next build.

Note the two lines near the top of the source code file:

rust
use exports::wasi::http::incoming_handler::Guest;
use wasi::http::types::*;

These two imports are bringing in the Guest trait to implement our function to be called whenever an incoming HTTP request is received, and the types that we'll use to interact with the HTTP request and response. These are the only two imports that we need to interact with the HTTP server capability.

rust
struct HttpServer;

impl Guest for HttpServer {
    fn handle(_request: IncomingRequest, response_out: ResponseOutparam) {
        let response = OutgoingResponse::new(Fields::new());
        response.set_status_code(200).unwrap();
        let response_body = response.body().unwrap();
        response_body
            .write()
            .unwrap()
            .blocking_write_and_flush(b"Hello from Rust!\n")
            .unwrap();
        OutgoingBody::finish(response_body, None).expect("failed to finish response body");
        ResponseOutparam::set(response_out, Ok(response));
    }
}

Within the handle method, the component receives the HTTP request, creates an OutgoingResponse and writes that response out back to the requesting http client (such as a curl command or a web browser).

Finally, we use the wit-bindgen generated macro export! to export the HttpServer struct as the incoming handler for the HTTP server capability. If you don't implement the Guest trait for your struct, the export! macro will give you an error at compile time noting which functions you need to implement.

rust
export!(HttpServer);

If you use an IDE that comes with code completion and hover-tooltips, you'll be able to see documentation and get strongly-typed guidance as you develop code to interact with the WASI interfaces.

info

The above component example works without any modification in wasmCloud, but is specifically built using standard WebAssembly tooling. You do not need to use a wasmCloud specific SDK to build components, and the above example will work directly with any WebAssembly runtime that supports the Wasm component model.

Something's missing

Before we get into modifying the scaffolding to create the rest of this component, take a look at what's not included in this code. This code returns an abstraction of an HTTP response. It is not tightly coupled to any particular HTTP server. Furthermore, you don't see the port number or server configuration options anywhere in the code. Finally, you can scale and compose this component any way you see fit without ever having to recompile or redeploy it.

This method of interface driven development is a core piece of the wasmCloud project philosophy. You should be able to write business logic in a language of your choice without having to worry about the non-functional requirements of your application, letting you configure loosely coupled abstractions at runtime. Moving on past our project scaffolding, the next step is to build and run our component.