restrustrust-rocket

How to return global object from a Rocket REST API?


I'm starting to learn Rust and the Rocket framework. How do I return my_universe that I created on the first line of main() when calling GET /universe/ports/21?

fn main() {
    let my_universe = universe::model::Universe::new();
    rocket::ignite().mount("/universe", routes![ports]).launch();
}

#[get("/ports/<id>")]
fn ports(id: u16) -> universe::model::Universe {
    // need to return my_universe here
}

The issue I'm having is that if I define my_universe within ports(), it'll recreate the the object on each request. Instead, I need the route to return the same my_universe object on each request.


Solution

  • Sharing non-mutable state in rocket is fairly easy. You can add the state with manage during the build of rocket.

    rocket::build()
      .manage(my_universe) // put the shared state here
      .mount("/universe", routes![ports])
    

    If you want to return this state in a route you will have to add both serde as a dependency and the json feature of rocket.

    [dependencies]
    rocket = { version = "0.5.0-rc.2", features = ["json"]}
    serde = "1.0.147"
    

    You can now annotate your struct with Serialize so we can send it as a JSON response later.

    #[derive(Serialize)]
    struct Universe {
        /* ... */
    }
    

    And access this state in your route with a &State parameter.

    #[get("/ports/<id>")]
    fn ports(id: u16, universe: &State<Universe>) -> Json<&Universe> {
        Json(universe.inner())
    }
    

    Here we can access the inner value of the state and return it as Json.


    So far, the state is immutable and can not be changed in the route which might not be what you want. Consider wrapping your state into a Mutex to allow for interior mutability.