diff --git a/README.md b/README.md index bd8a6d4a..8bec6956 100644 --- a/README.md +++ b/README.md @@ -2,58 +2,38 @@ This package makes it easy to run AWS Lambda Functions written in Rust. This workspace includes multiple crates: -- [![Docs](https://docs.rs/lambda_runtime_client/badge.svg)](https://docs.rs/lambda_runtime_client) **`lambda-runtime-client`** is a client SDK for the Lambda Runtime APIs. You probably don't need to use this crate directly! -- [![Docs](https://docs.rs/lambda_runtime/badge.svg)](https://docs.rs/lambda_runtime) **`lambda-runtime`** is a library that makes it easy to write Lambda functions in Rust. +- [![Docs](https://docs.rs/lambda/badge.svg)](https://docs.rs/lambda) **`lambda`** is a library that provides a Lambda runtime for applications written in Rust. - [![Docs](https://docs.rs/lambda_http/badge.svg)](https://docs.rs/lambda_http) **`lambda-http`** is a library that makes it easy to write API Gateway proxy event focused Lambda functions in Rust. ## Example function -The code below creates a simple function that receives an event with a `greeting` and `name` field and returns a `GreetingResponse` message for the given name and greeting. Notice: to run these examples, we require a minimum Rust version of 1.31. +The code below creates a simple function that receives an event with a `firstName` field and returns a message to the caller. Notice: this crate is tested against latest stable Rust. ```rust,no_run -use std::error::Error; - -use lambda_runtime::{error::HandlerError, lambda, Context}; -use log::{self, error}; -use serde_derive::{Deserialize, Serialize}; -use simple_error::bail; -use simple_logger; - -#[derive(Deserialize)] -struct CustomEvent { - #[serde(rename = "firstName")] - first_name: String, -} +use lambda::{handler_fn, Context}; +use serde_json::{json, Value}; -#[derive(Serialize)] -struct CustomOutput { - message: String, -} - -fn main() -> Result<(), Box> { - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler); +type Error = Box; +#[tokio::main] +async fn main() -> Result<(), Error> { + let func = handler_fn(func); + lambda::run(func).await?; Ok(()) } -fn my_handler(e: CustomEvent, c: Context) -> Result { - if e.first_name == "" { - error!("Empty first name in request {}", c.aws_request_id); - bail!("Empty first name"); - } +async fn func(event: Value, _: Context) -> Result { + let first_name = event["firstName"].as_str().unwrap_or("world"); - Ok(CustomOutput { - message: format!("Hello, {}!", e.first_name), - }) + Ok(json!({ "message": format!("Hello, {}!", first_name) })) } ``` -The code above is the same as the [basic example](https://github.com/awslabs/aws-lambda-rust-runtime/tree/master/lambda-runtime/examples/basic.rs) in the `lambda-runtime` crate. +The code above is the same as the [basic example](https://github.com/awslabs/aws-lambda-rust-runtime/blob/master/lambda/examples/hello-without-macro.rs) in the `lambda` crate. ### Deployment -There are currently multiple ways of building this package: manually, and with the [Serverless framework](https://serverless.com/framework/). +There are currently multiple ways of building this package: manually with the AWS CLI, and with the [Serverless framework](https://serverless.com/framework/). #### AWS CLI @@ -93,7 +73,7 @@ You can now test the function using the AWS CLI or the AWS Lambda console $ aws lambda invoke --function-name rustTest \ --payload '{"firstName": "world"}' \ output.json -$ cat output.json # Prints: {"message":"Hello, world!"} +$ cat output.json # Prints: {"message": "Hello, world!"} ``` **Note:** `--cli-binary-format raw-in-base64-out` is a required @@ -167,34 +147,14 @@ $ unzip -o \ # Ctrl-D to yield control back to your function ``` -## lambda-runtime-client - -Defines the `RuntimeClient` trait and provides its `HttpRuntimeClient` implementation. The client fetches events and returns output as `Vec`. - -For error reporting to the runtime APIs the library defines the `RuntimeApiError` trait and the `ErrorResponse` object. Custom errors for the APIs should implement the `to_response() -> ErrorResponse` method of the `RuntimeApiError` trait. +## `lambda` -## lambda-runtime +`lambda` is a library for authoring reliable and performant Rust-based AWS Lambda functions. At a high level, it provides a few major components: -This library makes it easy to create Rust executables for AWS lambda. The library defines a `lambda!()` macro. Call the `lambda!()` macro from your main method with an implementation the `Handler` type: +- `Handler`, a trait that defines interactions between customer-authored code and this library. +- `lambda::run`, function that runs an `Handler`. -```rust -pub trait Handler { - /// Run the handler. - fn run( - &mut self, - event: E, - ctx: Context - ) -> Result; -} -``` - -`Handler` provides a default implementation that enables you to provide a Rust closure or function pointer to the `lambda!()` macro. - -Optionally, you can pass your own instance of Tokio runtime to the `lambda!()` macro: -``` -let rt = tokio::runtime::Runtime::new()?; -lambda!(my_handler, rt); -``` +The function `handler_fn` converts a rust function or closure to `Handler`, which can then be run by `lambda::run`. ## AWS event objects @@ -205,11 +165,7 @@ This project does not currently include Lambda event struct definitions though w To serialize and deserialize events and responses, we suggest using the use the [`serde`](https://github.com/serde-rs/serde) library. To receive custom events, annotate your structure with Serde's macros: ```rust -extern crate serde; -extern crate serde_derive; -extern crate serde_json; - -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use serde_json::json; use std::error::Error; diff --git a/lambda/examples/hello-without-macro.rs b/lambda/examples/hello-without-macro.rs index 2aec334f..d94ee322 100644 --- a/lambda/examples/hello-without-macro.rs +++ b/lambda/examples/hello-without-macro.rs @@ -1,5 +1,5 @@ use lambda::{handler_fn, Context}; -use serde_json::Value; +use serde_json::{json, Value}; type Error = Box; @@ -11,5 +11,7 @@ async fn main() -> Result<(), Error> { } async fn func(event: Value, _: Context) -> Result { - Ok(event) + let first_name = event["firstName"].as_str().unwrap_or("world"); + + Ok(json!({ "message": format!("Hello, {}!", first_name) })) }