Skip to content

Commit 996fb9b

Browse files
authored
http-dynamodb example (#562)
* First commit. * Changed project name. * First set of edits from PR. * Fixed serde derserialization * Returned JSON of object commited to Dynamodb * Replaced printf with cloudwatch statement. * Added README, cleaned up comments. * Code formatting. Implemented clone on struct. * Replaced custom clone with derive. * Added 200 and 400 response codes. Co-authored-by: Justin Knoetzke <jfk@amazon.com>
1 parent 213e880 commit 996fb9b

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

examples/http-dynamodb/Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "http-dynamodb"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
7+
# Use cargo-edit(https://github.com/killercup/cargo-edit#installation)
8+
# to manage dependencies.
9+
# Running `cargo add DEPENDENCY_NAME` will
10+
# add the latest version of a dependency to the list,
11+
# and it will keep the alphabetic ordering for you.
12+
13+
[dependencies]
14+
simple-error = "0.2.3"
15+
serde_json = "1.0"
16+
serde = { version = "1.0", features = ["derive"] }
17+
lambda_http = { path = "../../lambda-http" }
18+
lambda_runtime = { path = "../../lambda-runtime" }
19+
aws-sdk-dynamodb = "0.21.0"
20+
aws-config = "0.51.0"
21+
tokio = { version = "1", features = ["macros"] }
22+
tracing = { version = "0.1.37"}
23+
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
24+
25+

examples/http-dynamodb/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# AWS Lambda Function example
2+
3+
## Build & Deploy
4+
5+
1. Install [cargo-lambda](https://github.com/cargo-lambda/cargo-lambda#installation)
6+
2. Build the function with `cargo lambda build --release`
7+
3. Deploy the function to AWS Lambda with `cargo lambda deploy --iam-role YOUR_ROLE`
8+
9+
## Build for ARM 64
10+
11+
Build the function with `cargo lambda build --release --arm64`
12+
13+
Setting up Dynamodb
14+
15+
1. Log into your account.
16+
2. Create a Dynamodb table with the name 'lambda_dyno_example' with the partition key of "username".
17+
3. Create IAM role with the permissions for Lambda, Cloudwatch and Dynamodb.
18+
19+

examples/http-dynamodb/src/main.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use aws_sdk_dynamodb::model::AttributeValue;
2+
use aws_sdk_dynamodb::{Client, Error as OtherError};
3+
use lambda_http::{run, service_fn, Body, Error, Request, Response};
4+
use tracing::info;
5+
6+
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
7+
pub struct Item {
8+
pub p_type: String,
9+
pub age: String,
10+
pub username: String,
11+
pub first: String,
12+
pub last: String,
13+
}
14+
15+
/// This is the main body for the function.
16+
/// Write your code inside it.
17+
/// You can see more examples in Runtime's repository:
18+
/// - https://github.com/awslabs/aws-lambda-rust-runtime/tree/main/examples
19+
async fn function_handler(event: Request) -> Result<Response<Body>, Error> {
20+
// Extract some useful information from the request
21+
let body = event.body();
22+
let s = std::str::from_utf8(&body).expect("invalid utf-8 sequence");
23+
//Log into Cloudwatch
24+
info!(payload = %s, "JSON Payload received");
25+
26+
//Serialze JSON into struct.
27+
//If JSON is incorrect, send back 400 with error.
28+
let item = match serde_json::from_str::<Item>(s) {
29+
Ok(item) => item,
30+
Err(err) => {
31+
let resp = Response::builder()
32+
.status(400)
33+
.header("content-type", "text/html")
34+
.body(err.to_string().into())
35+
.map_err(Box::new)?;
36+
return Ok(resp);
37+
}
38+
};
39+
40+
//Get config from environment.
41+
let config = aws_config::load_from_env().await;
42+
//Create the DynamoDB client.
43+
let client = Client::new(&config);
44+
45+
//Insert into the table.
46+
add_item(&client, item.clone(), "lambda_dyno_example").await?;
47+
48+
//Deserialize into json to return in the Response
49+
let j = serde_json::to_string(&item)?;
50+
51+
//Send back a 200 - success
52+
let resp = Response::builder()
53+
.status(200)
54+
.header("content-type", "text/html")
55+
.body(j.into())
56+
.map_err(Box::new)?;
57+
Ok(resp)
58+
}
59+
60+
#[tokio::main]
61+
async fn main() -> Result<(), Error> {
62+
tracing_subscriber::fmt()
63+
.with_max_level(tracing::Level::INFO)
64+
// disabling time is handy because CloudWatch will add the ingestion time.
65+
.without_time()
66+
.init();
67+
68+
run(service_fn(function_handler)).await
69+
}
70+
71+
// Add an item to a table.
72+
// snippet-start:[dynamodb.rust.add-item]
73+
pub async fn add_item(client: &Client, item: Item, table: &str) -> Result<(), OtherError> {
74+
let user_av = AttributeValue::S(item.username);
75+
let type_av = AttributeValue::S(item.p_type);
76+
let age_av = AttributeValue::S(item.age);
77+
let first_av = AttributeValue::S(item.first);
78+
let last_av = AttributeValue::S(item.last);
79+
80+
let request = client
81+
.put_item()
82+
.table_name(table)
83+
.item("username", user_av)
84+
.item("account_type", type_av)
85+
.item("age", age_av)
86+
.item("first_name", first_av)
87+
.item("last_name", last_av);
88+
89+
info!("adding item to DynamoDB");
90+
91+
let _resp = request.send().await?;
92+
93+
Ok(())
94+
}

0 commit comments

Comments
 (0)