Rust Serverless Microframework for AWS Lambda, inspired by AWS Chalice.
A traditional Japanese vessel, like a cup, is called "choko" and written "猪口".
🐗
- Declarative routing with path parameters (
/users/{user_id}) - Automatic JSON request body parsing
- Fluent response builder (
Response::json(...).with_status(201)) - Built-in 404 / 405 / 500 error responses
- Runs on API Gateway (REST API) + Lambda proxy integration
Add choko to your project:
[dependencies]
choko = { git = "https://github.com/velocitylabo/choko" }
tokio = { version = "1", features = ["full"] }
serde_json = "1.0"Create src/main.rs:
use choko::{Choko, Response, Error, serde_json};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Error> {
let mut app = Choko::new("my-api");
app.route("/", &["GET"], |_req| async {
Ok(Response::json(json!({"message": "Hello, choko!"})))
});
app.run().await
}// GET /users
app.route("/users", &["GET"], |_req| async {
Ok(Response::json(json!({"users": []})))
});
// POST /users
app.route("/users", &["POST"], |req| async move {
let name = req.json_body
.as_ref()
.and_then(|v| v.get("name"))
.and_then(|v| v.as_str())
.unwrap_or("anonymous");
Ok(Response::json(json!({"created": name})).with_status(201))
});
// Multiple methods on one route
app.route("/health", &["GET", "HEAD"], |_req| async {
Ok(Response::json(json!({"status": "ok"})))
});Use {param} syntax to capture URL segments:
app.route("/users/{user_id}", &["GET"], |req| async move {
let user_id = req.path_params.get("user_id").unwrap();
Ok(Response::json(json!({"user_id": user_id})))
});
app.route("/users/{user_id}/posts/{post_id}", &["GET"], |req| async move {
let user_id = req.path_params.get("user_id").unwrap();
let post_id = req.path_params.get("post_id").unwrap();
Ok(Response::json(json!({
"user_id": user_id,
"post_id": post_id
})))
});The handler receives a Request with:
| Field | Type | Description |
|---|---|---|
path_params |
HashMap<String, String> |
URL path parameters |
query_params |
HashMap<String, Vec<String>> |
Query string parameters (multi-value) |
headers |
HashMap<String, String> |
HTTP headers |
body |
Option<String> |
Raw request body |
json_body |
Option<Value> |
Parsed JSON body |
app.route("/search", &["GET"], |req| async move {
let query = req.query_params.get("q")
.and_then(|v| v.first())
.cloned()
.unwrap_or_default();
Ok(Response::json(json!({"query": query})))
});// 200 JSON (default)
Response::json(json!({"ok": true}))
// Custom status code
Response::json(json!({"id": 1})).with_status(201)
// Custom headers
Response::json(json!({}))
.with_header("X-Request-Id", "abc-123")
.with_header("Cache-Control", "no-cache")If a handler returns Err, choko automatically responds with HTTP 500:
app.route("/risky", &["GET"], |_req| async {
let result = tokio::fs::read_to_string("/tmp/data.json").await;
match result {
Ok(data) => Ok(Response::json(json!({"data": data}))),
Err(e) => Err(e.into()), // -> 500 {"error": "Internal Server Error"}
}
});Unmatched paths return 404, and wrong HTTP methods return 405.
- cargo-make:
cargo install cargo-make - AWS CLI (configured with valid credentials)
# Build release binary
cargo make build-release
# Run tests
cargo make test
# Create Lambda deployment zip (bootstrap.zip)
cargo make packageInstall the CLI:
cargo install choko --features cliDeploy to AWS Lambda + API Gateway:
choko deploy --role-arn arn:aws:iam::123456789012:role/my-lambda-roleThis single command will:
- Build a release binary and package
bootstrap.zip - Create (or update) a Lambda function using the
provided.al2023runtime - Create (or update) an API Gateway REST API with
{proxy+}integration - Deploy to a stage and print the endpoint URL
| Option | Env var | Default | Description |
|---|---|---|---|
--role-arn |
CHOKO_ROLE_ARN |
(required) | IAM role ARN for the Lambda function |
--region |
AWS_DEFAULT_REGION |
ap-northeast-1 |
AWS region |
--function-name |
Cargo.toml name |
Lambda function name | |
--stage |
prod |
API Gateway stage name | |
--memory |
128 |
Lambda memory (MB) | |
--timeout |
30 |
Lambda timeout (seconds) | |
--target |
x86_64-unknown-linux-gnu |
Rust target triple for cross-compilation |
--targetにaarch64-unknown-linux-gnuを指定すると、Lambda の architecture が自動的にarm64に設定されます。
choko package
choko package --target aarch64-unknown-linux-gnu # ARM64 向けMIT