Run Rust web server frameworks on AWS Lambda. Currently, it supports Actix web, axum, Rocket, warp.
- API Gateway HTTP API with payload format version 1.0
- Application Load Balancer (ALB)
Cargo.toml
[[bin]]
name = "bootstrap"
path = "src/main.rs"
[dependencies]
lambda-web = { version = "0.1.8", features=["actix4"] }
main.rs
use lambda_web::actix_web::{self, get, App, HttpServer, Responder};
use lambda_web::{is_running_on_lambda, run_actix_on_lambda, LambdaError};
#[get("/")]
async fn hello() -> impl Responder {
format!("Hello")
}
#[actix_web::main]
async fn main() -> Result<(),LambdaError> {
let factory = move || {
App::new().service(hello)
};
if is_running_on_lambda() {
// Run on AWS Lambda
run_actix_on_lambda(factory).await?;
} else {
// Local server
HttpServer::new(factory)
.bind("127.0.0.1:8080")?
.run()
.await?;
}
Ok(())
}
Cargo.toml
[[bin]]
name = "bootstrap"
path = "src/main.rs"
[dependencies]
lambda-web = { version = "0.1.8", features=["hyper"] }
axum = "0.3"
tokio = { version = "1" }
main.rs
use axum::{routing::get, Router};
use lambda_web::{is_running_on_lambda, run_hyper_on_lambda, LambdaError};
use std::net::SocketAddr;
// basic handler that responds with a static string
async fn root() -> &'static str {
"Hello, World!"
}
#[tokio::main]
async fn main() -> Result<(), LambdaError> {
// build our application with a route
let app = Router::new().route("/", get(root));
if is_running_on_lambda() {
// Run app on AWS Lambda
run_hyper_on_lambda(app).await?;
} else {
// Run app on local server
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
axum::Server::bind(&addr).serve(app.into_make_service()).await?;
}
Ok(())
}
Cargo.toml
[[bin]]
name = "bootstrap"
path = "src/main.rs"
[dependencies]
lambda-web = { version = "0.1.8", features=["rocket05"] }
rocket = "0.5.0-rc.1"
main.rs
use rocket::{self, get, routes};
use lambda_web::{is_running_on_lambda, launch_rocket_on_lambda, LambdaError};
#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
#[rocket::main]
async fn main() -> Result<(), LambdaError> {
let rocket = rocket::build().mount("/", routes![hello]);
if is_running_on_lambda() {
// Launch on AWS Lambda
launch_rocket_on_lambda(rocket).await?;
} else {
// Launch local server
rocket.launch().await?;
}
Ok(())
}
Cargo.toml
[[bin]]
name = "bootstrap"
path = "src/main.rs"
[dependencies]
lambda-web = { version = "0.1.8", features=["hyper"] }
warp = "0.3"
tokio = { version = "1" }
main.rs
use lambda_web::{is_running_on_lambda, run_hyper_on_lambda, LambdaError};
use warp::Filter;
#[tokio::main]
async fn main() -> Result<(), LambdaError> {
// GET /hello/warp => 200 OK with body "Hello, warp!"
let hello = warp::path!("hello" / String).map(|name| format!("Hello, {}", name));
if is_running_on_lambda() {
// Run on AWS Lambda
run_hyper_on_lambda(warp::service(hello)).await?;
} else {
// Run local server
warp::serve(hello).run(([127, 0, 0, 1], 8080)).await;
}
Ok(())
}
As of writing (Nov, 2021), we have two options to run Rust on AWS Lambda: Amazon Linux 2 custom runtime or Docker container image.
I recommend ZIP deploy to Amazon Linux 2 custom runtime (provided.al2
) because it's faster cold start time than container image.
To build Amazon Linux 2 compatible binary, see Deploy.md for more details.
- Create lambda function with
provided.al2
custom runtime. Choose "Provide your own bootstrap on Amazon Linux 2" . - Upload ZIP file described above.
- IAM role, memory settings, etc. are as your demands.
As sample code above consumes only 30MB of memory, many simple Rust app can fit in 128MB setting.
- Create HTTP API
- Create single route "$default" and attach Lambda integration. Make sure, payload format version is "2.0"
- Create REST API
- Create two resources:
- ANY method on route
/
and attach Lambda proxy integration. - ANY method on route
/{proxy+}
and attach Lambda proxy integration.
- ANY method on route
- In settings tab, add
*/*
binary media type. - Then, deploy API to stage.