diff --git a/examples/http-dynamodb/Cargo.toml b/examples/http-dynamodb/Cargo.toml new file mode 100644 index 00000000..73ff7c24 --- /dev/null +++ b/examples/http-dynamodb/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "http-dynamodb" +version = "0.1.0" +edition = "2021" + + +# Use cargo-edit(https://github.com/killercup/cargo-edit#installation) +# to manage dependencies. +# Running `cargo add DEPENDENCY_NAME` will +# add the latest version of a dependency to the list, +# and it will keep the alphabetic ordering for you. + +[dependencies] +simple-error = "0.2.3" +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +lambda_http = { path = "../../lambda-http" } +lambda_runtime = { path = "../../lambda-runtime" } +aws-sdk-dynamodb = "0.21.0" +aws-config = "0.51.0" +tokio = { version = "1", features = ["macros"] } +tracing = { version = "0.1.37"} +tracing-subscriber = { version = "0.3", features = ["env-filter"] } + + diff --git a/examples/http-dynamodb/README.md b/examples/http-dynamodb/README.md new file mode 100644 index 00000000..cb53c868 --- /dev/null +++ b/examples/http-dynamodb/README.md @@ -0,0 +1,19 @@ +# AWS Lambda Function example + +## Build & Deploy + +1. Install [cargo-lambda](https://github.com/cargo-lambda/cargo-lambda#installation) +2. Build the function with `cargo lambda build --release` +3. Deploy the function to AWS Lambda with `cargo lambda deploy --iam-role YOUR_ROLE` + +## Build for ARM 64 + +Build the function with `cargo lambda build --release --arm64` + +Setting up Dynamodb + +1. Log into your account. +2. Create a Dynamodb table with the name 'lambda_dyno_example' with the partition key of "username". +3. Create IAM role with the permissions for Lambda, Cloudwatch and Dynamodb. + + diff --git a/examples/http-dynamodb/src/main.rs b/examples/http-dynamodb/src/main.rs new file mode 100644 index 00000000..2733e65d --- /dev/null +++ b/examples/http-dynamodb/src/main.rs @@ -0,0 +1,94 @@ +use aws_sdk_dynamodb::model::AttributeValue; +use aws_sdk_dynamodb::{Client, Error as OtherError}; +use lambda_http::{run, service_fn, Body, Error, Request, Response}; +use tracing::info; + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct Item { + pub p_type: String, + pub age: String, + pub username: String, + pub first: String, + pub last: String, +} + +/// This is the main body for the function. +/// Write your code inside it. +/// You can see more examples in Runtime's repository: +/// - https://github.com/awslabs/aws-lambda-rust-runtime/tree/main/examples +async fn function_handler(event: Request) -> Result, Error> { + // Extract some useful information from the request + let body = event.body(); + let s = std::str::from_utf8(&body).expect("invalid utf-8 sequence"); + //Log into Cloudwatch + info!(payload = %s, "JSON Payload received"); + + //Serialze JSON into struct. + //If JSON is incorrect, send back 400 with error. + let item = match serde_json::from_str::(s) { + Ok(item) => item, + Err(err) => { + let resp = Response::builder() + .status(400) + .header("content-type", "text/html") + .body(err.to_string().into()) + .map_err(Box::new)?; + return Ok(resp); + } + }; + + //Get config from environment. + let config = aws_config::load_from_env().await; + //Create the DynamoDB client. + let client = Client::new(&config); + + //Insert into the table. + add_item(&client, item.clone(), "lambda_dyno_example").await?; + + //Deserialize into json to return in the Response + let j = serde_json::to_string(&item)?; + + //Send back a 200 - success + let resp = Response::builder() + .status(200) + .header("content-type", "text/html") + .body(j.into()) + .map_err(Box::new)?; + Ok(resp) +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::INFO) + // disabling time is handy because CloudWatch will add the ingestion time. + .without_time() + .init(); + + run(service_fn(function_handler)).await +} + +// Add an item to a table. +// snippet-start:[dynamodb.rust.add-item] +pub async fn add_item(client: &Client, item: Item, table: &str) -> Result<(), OtherError> { + let user_av = AttributeValue::S(item.username); + let type_av = AttributeValue::S(item.p_type); + let age_av = AttributeValue::S(item.age); + let first_av = AttributeValue::S(item.first); + let last_av = AttributeValue::S(item.last); + + let request = client + .put_item() + .table_name(table) + .item("username", user_av) + .item("account_type", type_av) + .item("age", age_av) + .item("first_name", first_av) + .item("last_name", last_av); + + info!("adding item to DynamoDB"); + + let _resp = request.send().await?; + + Ok(()) +}