From 0aa45326d0686438bd17a2b71a0e4f957f4e5971 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Fri, 15 Dec 2023 10:23:46 +1000 Subject: [PATCH 01/10] Update readme to latest template syntax Signed-off-by: tpmccallum tim.mccallum@fermyon.com This readme is also visible from https://crates.io/crates/spin-sdk Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 113 +++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index b505d676a..d40871723 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -2,80 +2,105 @@ The Spin Rust SDK makes it easy to build Spin components in Rust. -### Writing Spin HTTP components in Rust +### Writing Spin HTTP Components in Rust This library simplifies writing Spin HTTP components. Below is an example of such a component: ```rust // lib.rs -use anyhow::Result; -use spin_sdk::{ - http::{Request, Response}, - http_component, -}; +use spin_sdk::http::{IntoResponse, Request, Response}; +use spin_sdk::http_component; /// A simple Spin HTTP component. #[http_component] -fn hello_world(req: Request) -> Result { - println!("{:?}", req.headers); - Ok(Response::new_with_headers(200, &[] "Hello, Fermyon!")) +fn handle_hello_world(req: Request) -> anyhow::Result { + 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 in the function above: +The important things to note about the function above are: -- the `spin_sdk::http_component` macro — this marks the function as the - entrypoint for the Spin component -- the function signature — `fn hello_world(req: Request) -> Result` — -`req` can be any number of types including the built in `Request` type or -the `http::Request` from the popular `http` crate. Likewise, the response type -can be many things including the built in `Response` type or the `http::Response` type -from the `http` crate. +- the `spin_sdk::http_component` macro marks the function as the entry point for the Spin component, +- in the function signature (`fn handle_hello_world(req: Request) -> anyhow::Result`), `req` can be any number of types, including the built-in `Request` type or the `http::Request` from the popular `http` crate +- in the function signature, the response type can be many things, including `anyhow::Result` (as shown above) or the `http::Response` type from the `http` crate (e.g. `Result`). Note - Using the `http` crate will require you to add it, e.g. `cargo install http`. ### Making outbound HTTP requests -Let's see an example where the component makes an outbound HTTP request to a -server, modifies the result, then returns it: +Let's see an example where the component makes an outbound HTTP request to a server, modifies the result, and then returns it: ```rust +use anyhow::Result; +use spin_sdk::{ + http::{IntoResponse, Request, Method, Response}, + http_component, +}; + #[http_component] -async fn hello_world(_req: Request) -> Result { - let mut res: http::Response = spin_sdk::http::send( - http::Request::builder() - .method("GET") - .uri("https://fermyon.com") - .body(())?, - ).await?; +async fn handle_hello_world(_req: Request) -> Result { + // Create the outbound request object + let req = Request::builder() + .method(Method::Get) + .uri("https://random-data-api.fermyon.app/animals/json") + .build(); - res.headers_mut() - .insert(http::header::SERVER, "spin/0.1.0".try_into()?); + // Send the request and await the response + let res: Response = spin_sdk::http::send(req).await?; + println!("{:?}", res); // log the response Ok(res) } - ``` -In order for the component above to be allowed to make the outbound HTTP -request, the destination host must be declared in the Spin application -configuration: +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): ```toml -[[component]] -id = "hello" -source = "target/wasm32-wasi/release/spinhelloworld.wasm" -allowed_outbound_hosts = [ "https://fermyon.com" ] -[component.trigger] -route = "/hello" +spin_manifest_version = 2 + +[application] +name = "hello_world" +version = "0.1.0" +authors = ["Your Name "] +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"] ``` -Making a request to this component, we can see the appended header, and that the -response contains the expected body: +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`: + +```bash +$ 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) ``` -$ curl -I localhost:3000/hello + +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: + +```bash +$ curl -i localhost:3000 HTTP/1.1 200 OK -content-length: 29350 -content-type: text/html; charset=utf-8 -server: spin/0.1.0 +content-length: 77 +content-type: application/json + +{"timestamp":1702599575198,"fact":"Sharks lay the biggest eggs in the world"} ``` From 97cc85386a1ec97a5cbca3b892d5b2a450e4622a Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Fri, 15 Dec 2023 10:25:50 +1000 Subject: [PATCH 02/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index d40871723..a4546fa11 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -30,7 +30,7 @@ The important things to note about the function above are: - in the function signature (`fn handle_hello_world(req: Request) -> anyhow::Result`), `req` can be any number of types, including the built-in `Request` type or the `http::Request` from the popular `http` crate - in the function signature, the response type can be many things, including `anyhow::Result` (as shown above) or the `http::Response` type from the `http` crate (e.g. `Result`). Note - Using the `http` crate will require you to add it, e.g. `cargo install http`. -### Making outbound HTTP requests +### Making Outbound HTTP Requests Let's see an example where the component makes an outbound HTTP request to a server, modifies the result, and then returns it: From b8aa1d7a38dfc26f7c6c5719543b5d24480951ec Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Fri, 15 Dec 2023 10:27:02 +1000 Subject: [PATCH 03/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index a4546fa11..e04f6dc2f 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -80,6 +80,8 @@ command = "cargo build --target wasm32-wasi --release" watch = ["src/**/*.rs", "Cargo.toml"] ``` +## Building and Running the Spin Application + 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`: ```bash From 5af7724eaac0fae5b91914a02d8bb90b4da224d6 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Fri, 15 Dec 2023 10:28:23 +1000 Subject: [PATCH 04/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index e04f6dc2f..91ea2cfba 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -80,7 +80,7 @@ command = "cargo build --target wasm32-wasi --release" watch = ["src/**/*.rs", "Cargo.toml"] ``` -## Building and Running the Spin Application +### Building and Running the Spin Application 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`: From 190f9cc9dbf6506ec5a7ef3e0236581cef14a3b2 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Mon, 18 Dec 2023 11:24:02 +1000 Subject: [PATCH 05/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Co-authored-by: Ryan Levick Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index 91ea2cfba..6f717f948 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -27,7 +27,7 @@ fn handle_hello_world(req: Request) -> anyhow::Result { The important things to note about the function above are: - the `spin_sdk::http_component` macro marks the function as the entry point for the Spin component, -- in the function signature (`fn handle_hello_world(req: Request) -> anyhow::Result`), `req` can be any number of types, including the built-in `Request` type or the `http::Request` from the popular `http` crate +- in the function signature (`fn handle_hello_world(req: Request) -> anyhow::Result`), `req` can be any number of types, including the built-in `Request` type or the `http::Request` type from the popular `http` crate - in the function signature, the response type can be many things, including `anyhow::Result` (as shown above) or the `http::Response` type from the `http` crate (e.g. `Result`). Note - Using the `http` crate will require you to add it, e.g. `cargo install http`. ### Making Outbound HTTP Requests From cce3ed5a12fb4361183d6a8095d13ff9c80a3625 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Mon, 18 Dec 2023 11:24:27 +1000 Subject: [PATCH 06/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Co-authored-by: Ryan Levick Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index 6f717f948..a85e000a1 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -28,7 +28,8 @@ The important things to note about the function above are: - the `spin_sdk::http_component` macro marks the function as the entry point for the Spin component, - in the function signature (`fn handle_hello_world(req: Request) -> anyhow::Result`), `req` can be any number of types, including the built-in `Request` type or the `http::Request` type from the popular `http` crate -- in the function signature, the response type can be many things, including `anyhow::Result` (as shown above) or the `http::Response` type from the `http` crate (e.g. `Result`). Note - Using the `http` crate will require you to add it, e.g. `cargo install http`. +- in the function signature, the response type can be anything that implements `IntoResponse` meaning the return type can any number of things including `anyhow::Result` (as shown above), `impl IntoResponse`, `Response`, `anyhow::Result`, or even the `http::Response` type from the `http` crate. + - Note: Using the `http` crate will require you to add it to your Cargo.toml manifest (i.e., `cargo add http`). ### Making Outbound HTTP Requests From 3e636033b3baa3254e6e0f6335abde18faedc15d Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Mon, 18 Dec 2023 11:28:31 +1000 Subject: [PATCH 07/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index a85e000a1..e040f1dfe 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -36,7 +36,6 @@ The important things to note about the function above are: Let's see an example where the component makes an outbound HTTP request to a server, modifies the result, and then returns it: ```rust -use anyhow::Result; use spin_sdk::{ http::{IntoResponse, Request, Method, Response}, http_component, From 87ad06d5c3cbd25fd7d50ea5c882614c97cbe766 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Mon, 18 Dec 2023 11:38:21 +1000 Subject: [PATCH 08/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index e040f1dfe..bc8544057 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -105,4 +105,3 @@ content-length: 77 content-type: application/json {"timestamp":1702599575198,"fact":"Sharks lay the biggest eggs in the world"} -``` From d37d9c044d5da802733b139c532ac47a6a345d2f Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Wed, 20 Dec 2023 09:02:22 +1000 Subject: [PATCH 09/10] Update sdk/rust/README.md Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index bc8544057..d9ac043de 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -2,6 +2,10 @@ The Spin Rust SDK makes it easy to build Spin components in Rust. +## Fermyon Developer Home + +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](https://developer.fermyon.com/). This resource includes [a page on installing Spin](https://developer.fermyon.com/spin/v2/install#installing-spin), [a quickstart guide](https://developer.fermyon.com/spin/v2/quickstart), and [a language support overview page](https://developer.fermyon.com/spin/v2/language-support-overview). 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. + ### Writing Spin HTTP Components in Rust This library simplifies writing Spin HTTP components. Below is an example of From 620afd7df66fdc06dbabf161998fcb6dfda563b6 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Thu, 21 Dec 2023 08:19:03 +1000 Subject: [PATCH 10/10] Add backticks to last code block in file Signed-off-by: tpmccallum tim.mccallum@fermyon.com Signed-off-by: Timothy McCallum --- sdk/rust/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/rust/README.md b/sdk/rust/README.md index d9ac043de..1e23a4e36 100644 --- a/sdk/rust/README.md +++ b/sdk/rust/README.md @@ -109,3 +109,4 @@ content-length: 77 content-type: application/json {"timestamp":1702599575198,"fact":"Sharks lay the biggest eggs in the world"} +```