The Spin Rust SDK makes it easy to build Spin components in Rust.
This README
file provides a few examples, such as writing Spin HTTP components in Rust and making outbound HTTP requests. For comprehensive information, visit the official Fermyon Developer Home. This resource includes a page on installing Spin, a quickstart guide, and a language support overview page. The latter lists all of Spin's features—including key-value storage, SQLite, MySQL, Redis, Serverless AI, etc.—and their implementation in specific languages such as Rust, TS/JS, Python, and TinyGo.
This library simplifies writing Spin HTTP components. Below is an example of such a component:
// lib.rs
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
/// A simple Spin HTTP component.
#[http_component]
fn handle_hello_world(req: Request) -> anyhow::Result<impl IntoResponse> {
println!("Handling request to {:?}", req.header("spin-full-url"));
Ok(Response::builder()
.status(200)
.header("content-type", "text/plain")
.body("Hello, Fermyon")
.build())
}
The important things to note about the function above are:
spin_sdk::http_component
macro marks the function as the entry point for the Spin component,fn handle_hello_world(req: Request) -> anyhow::Result<impl IntoResponse>
), req
can be any number of types, including the built-in Request
type or the http::Request
type from the popular http
crateIntoResponse
meaning the return type can any number of things including anyhow::Result<impl IntoResponse>
(as shown above), impl IntoResponse
, Response
, anyhow::Result<Response>
, or even the http::Response
type from the http
crate.
http
crate will require you to add it to your Cargo.toml manifest (i.e., cargo add http
).Let's see an example where the component makes an outbound HTTP request to a server, modifies the result, and then returns it:
use spin_sdk::{
http::{IntoResponse, Request, Method, Response},
http_component,
};
#[http_component]
async fn handle_hello_world(_req: Request) -> Result<impl IntoResponse> {
// Create the outbound request object
let req = Request::builder()
.method(Method::Get)
.uri("https://random-data-api.fermyon.app/animals/json")
.build();
// Send the request and await the response
let res: Response = spin_sdk::http::send(req).await?;
println!("{:?}", res); // log the response
Ok(res)
}
For the component above to be allowed to make the outbound HTTP request, the destination host must be declared, using the allowed_outbound_hosts
configuration, in the Spin application's manifest (the spin.toml
file):
spin_manifest_version = 2
[application]
name = "hello_world"
version = "0.1.0"
authors = ["Your Name <your-name@example.com>"]
description = "An example application"
[[trigger.http]]
route = "/..."
component = "hello-world"
[component.hello-world]
source = "target/wasm32-wasi/release/hello_world.wasm"
allowed_outbound_hosts = ["https://random-data-api.fermyon.app"]
[component.hello-world.build]
command = "cargo build --target wasm32-wasi --release"
watch = ["src/**/*.rs", "Cargo.toml"]
Spin build can be used to build all components defined in the Spin manifest file at the same time, and also has a flag that starts the application after finishing the compilation, spin build --up
:
$ spin build --up
Building component hello-world with `cargo build --target wasm32-wasi --release`
Finished release [optimized] target(s) in 0.12s
Finished building all Spin components
Logging component stdio to ".spin/logs/"
Serving http://127.0.0.1:3000
Available Routes:
hello-world: http://127.0.0.1:3000 (wildcard)
Once our application is running, we can make a request (by visiting http://localhost:3000/
in a web browser) or using curl
as shown below:
$ curl -i localhost:3000
HTTP/1.1 200 OK
content-length: 77
content-type: application/json
{"timestamp":1702599575198,"fact":"Sharks lay the biggest eggs in the world"}