Welcome to the new Golem Cloud Docs! 👋
Documentation
Rust

Rust

Make sure you have the latest Rust version installed and have cargo in the path. The recommended way to do so is using https://rustup.rs (opens in a new tab):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup install stable && rustup default stable
rustup target add wasm32-wasi

The easiest way to build Golem components with Rust is using the compatible version of https://github.com/bytecodealliance/cargo-component (opens in a new tab). A prerequisite of cargo-component is protobuf (at least 15), which can be installed as described on http://google.github.io/proto-lens/installing-protoc.html (opens in a new tab):

brew install protobuf

Then install the required version of cargo-component:

cargo install --force --locked cargo-component@0.13.2
cargo component --version
cargo-component 0.13.2 (wasi:040ec92)
💡

Read the following section if your IDE is not recognizing the generated bindings in Rust projects using cargo-component: https://github.com/bytecodealliance/cargo-component#using-rust-analyzer (opens in a new tab)

💡

The cargo build tool does not know how to build WebAssembly components alone. The above installed cargo-component tool is an extension to it adding a new subset of commands starting with cargo component ... Using these new commands such as cargo component build makes sure the compiler toolchain produces a WebAssembly component model target and that all the necessary bindings are generated.

The easiest way to get started once the tooling is installed is to use the golem new command as described in the Quickstart.

If you prefer to set up your project manually, you first need to create a new component:

cargo component new --reactor golem-test

Modify the interface definition for the component in wit/world.wit:

package my:component;
 
interface api {
  record product-item {
    product-id: string,
    name: string,
    price: float32,
    quantity: u32,
  }
 
  record order {
    order-id: string,
    items: list<product-item>,
    total: float32,
    timestamp: u64,
  }
 
  record order-confirmation {
    order-id: string,
  }
 
  variant checkout-result {
    error(string),
    success(order-confirmation),
  }
 
  initialize-cart: func(user-id: string) -> ();
 
  add-item: func(item: product-item) -> ();
 
  remove-item: func(product-id: string) -> ();
 
  update-item-quantity: func(product-id: string, quantity: u32) -> ();
 
  checkout: func() -> checkout-result;
 
  get-cart-contents: func() -> list<product-item>;
}
 
world shopping-cart {
  export api;
}

The functions exported in the world in this file will be exposed by Golem.

In the Rust source code you generate and import the exported symbols as:

mod bindings;
use bindings::exports::my::component::api::*;

and then implement the Guest trait from the interface definition:

struct Component;
 
impl Guest for Component {
  fn initialize_cart(user_id: String) {
    // ...
  }
  // ...
}
 
bindings::export!(Component with_types_in bindings);

The struct you implement the trait for must be called Component!

State in Rust

When running a Golem component you don't have to care about concurrent access of global state - each worker based on the component runs completely separated. The worker's state is persisted by Golem so all you have to do for state handling is to store data in a global mutable variable.

In Rust we recommend the following pattern for this:

struct State {
    user_id: String,
    items: Vec<ProductItem>,
}
 
thread_local! {
    static STATE: RefCell<State> = RefCell::new(State {
        user_id: String::new(),
        items: vec![],
    });
}
 
// ...
 
fn add_item(item: ProductItem) {
        STATE.with_borrow_mut(|state| {
            println!(
                "Adding item {:?} to the cart of user {}",
                item, state.user_id
            );
 
            state.items.push(item);
        });
    }

WASI Preview1 APIs

Rust already support WASI Preview1 so by using its standard libraries to work with IO, file systems, random numbers will automatically work with Golem.

WASI Preview2 APIs

To use any of the new WASI APIs, you need to explicitly put the WASI interface definitions in the wit/deps folder. Use the WASI interface definitions packaged with golem-cli to make sure they are compatible with the version implemented by Golem as these interfaces are still not finalized.

The dependencies has to be added to the Cargo.toml file for cargo-component, for example:

[package.metadata.component.target.dependencies]
"wasi:io" = { path = "wit/deps/io" }
"wasi:http" = { path = "wit/deps/http" }

This allows using these WIT packages in your main WIT file, making them available from Rust:

import wasi:io/poll@0.2.0;
import wasi:io/streams@0.2.0;
import wasi:http/types@0.2.0;
import wasi:http/outgoing-handler@0.2.0;

Alternatively you can depend on the golem-rust library (see below) which already imports all the WASI interfaces and exports the generated bindings for you.

Golem Rust Library

The golem-rust (opens in a new tab) library provides a set of higher level idiomatic Rust wrappers for Golem specific functionality, as well as exporting bindings for the official WASI interfaces.

Using this library is optional when building Golem components in Rust, but it provides a nicer experience than doing everything manually.

To use it, add the following dependency to your component's Cargo.toml:

[dependencies]
golem-rust = "0.3.0"

See the Transaction API page for more information about what this library provides.

HTTP

Golem implements the WASI-HTTP interface so any library built on that could be used from Golem components to communicate with external services.

At the time of writing the only library available is our fork of reqwest

To use it, just add the following dependency to your component's Cargo.toml:

[dependencies]
reqwest = { git = "https://github.com/golemcloud/reqwest", branch = "update-jun-2024", features = ["json"] }

There is no need to manually add the WASI-HTTP interfaces to your wit/deps folder.

The fork provides the same API as the official reqwest blocking API, so please use the library's documentation for more information: https://docs.rs/reqwest/latest/reqwest/ (opens in a new tab)

Compiling Rust

Creating the Golem component is just running:

cargo component build --release

The output is target/wasm32-wasi/release/component_name.wasm and it is ready to be uploaded to Golem Cloud. (the output file's name depends on the project!)