Production grade api with Rocket & Rust

Amay B
CoderHack.com
Published in
2 min readSep 17, 2023
Photo by NASA on Unsplash

You’ll need to install Rust and the Rocket framework.

curl https://sh.rustup.rs -sSf | sh

Then install Rocket:

cargo install rocket

Create a new Rocket project:

rocket new my-project

This will create a Cargo.toml and src/main.rs. Cargo.toml contains project metadata and dependencies. src/main.rs contains your Rocket app.

2. Handling Requests

Define routes with the route attribute:

#[get("/hello/<name>")] 
fn say_hello(name: String) -> String {
format!("Hello, {}!", name)
}

This will match GET requests to /hello/<name> and extract the name parameter.

You can also have POST requests:

#[post("/posts", format = "application/json", data = "<new_post>")]
fn create_post(new_post: Json<Post>) -> Json<Post> {
// Create post
Json(new_post.into_inner())
}

Use request guards to validate requests, access request data like query parameters, forms, and JSON.

3. Responding

Return strings, JSON, or templates:

#[get("/")]
fn index() -> Template {
Template::render("index", ...) // Load a Twig template
}

#[get("/posts")]
fn posts() -> Json<Vec<Post>> {
let posts = ...; // Load list of posts from DB
Json(posts)
}

Set status codes and headers:

fn not_found() -> status::NotFound<String> {
status::NotFound("Nothing found".into())
}

fn create_post(post: Json<Post>) -> (status::Created, json::Json<Post>) {
...
}

Redirect with status::SeeOther:

fn old_route() -> status::SeeOther { 
status::SeeOther(uri!(new_route))
}

4. State management

Rocket gives you managed state to store database pools, caches, etc. You can access these in your routes:

#[get("/posts")]
fn list_posts(db: State<DbConn>) -> Json<Vec<Post>> {
let posts = db.run(|c| c.load_posts()).unwrap();
Json(posts)
}

You can use databases like Diesel or rusqlite and cache with r2d2. Cookies and sessions can be managed with rocket_contrib.

5. Deployment

Build a release with cargo build --release. Host on AWS, GCP, Azure, Digital Ocean, etc. Configure Rocket for production with:

[production]
port = 8000
workers = 4
secret_key = "my_secret_key"

Set up health checks and logging.

6. Testing

Unit test with Rust’s std::test:

#[test]
fn test_say_hello() {
assert_eq!(say_hello("John"), "Hello, John!");
}

Integration test with Rocket:

#[test]
fn test_list_posts() {
let client = Client::new(App::new().manage(MockDb::new())).unwrap();
let response = client.get("/posts").dispatch();
assert_eq!(response.body_string(), "[]");
}

Property based testing with proptest. Mock external services.

7. Additional topics

Authentication with JWTs or sessions, authorization, file uploading, CORS, rate limiting, async/await, and more!

--

--