############################################################################### # Release info: displayed between bars in the header ############################################################################### [release] version = "0.5.0" date = "Nov 17, 2023" ############################################################################### # Top features: displayed in the header under the introductory text. ############################################################################### [[top_features]] title = "Type Safe" text = "Type safety turned up to 11 means security and robustness come at compile-time." image = "helmet" button = "Learn More" url = "overview/#how-rocket-works" width = "69px" height = "71px" [[top_features]] title = "Boilerplate Free" text = "Spend your time writing code that really matters and let Rocket handle the rest." image = "robot-free" button = "See Examples" url = "overview/#anatomy-of-a-rocket-application" width = "78px" height = "71px" [[top_features]] title = "Easy To Use" text = "Simple, intuitive APIs make Rocket approachable, no matter your background." image = "sun" button = "Get Started" url = "guide" margin = 2 width = "68px" height = "69px" [[top_features]] title = "Extensible" text = "Create your own first-class primitives that any Rocket application can use." image = "telescope" button = "See How" url = "overview/#anatomy-of-a-rocket-application" margin = 9 width = "71px" height = "62px" ############################################################################### # Sections: make sure there are an odd number so colors work out. ############################################################################### [[sections]] title = "Hello, Rocket!" code = ''' #[macro_use] extern crate rocket; #[get("/hello//")] fn hello(name: &str, age: u8) -> String { format!("Hello, {} year old named {}!", age, name) } #[launch] fn rocket() -> _ { rocket::build().mount("/", routes![hello]) } ''' text = ''' This is a **complete Rocket application**. It does exactly what you would expect. If you were to visit **/hello/John/58**, you’d see: Hello, 58 year old named John! If someone visits a path with an `` that isn’t a `u8`, Rocket doesn’t just call `hello`. Instead, it tries other matching routes or returns a **404**. ''' [[sections]] title = "Forms? Check!" code = ''' #[derive(FromForm)] struct Task<'r> { #[field(validate = len(1..))] description: &'r str, completed: bool } #[post("/", data = "")] fn new(task: Form>) -> Flash { Flash::success(Redirect::to(uri!(home)), "Task added.") } ''' text = ''' Form handling **is simple, declarative, and complete**: derive [`FromForm`](@api/rocket/derive.FromForm.html) for your structure and set the `data` parameter to a `Form` type. Rocket automatically **parses and validates** the form data into your structure and calls your function. File uploads? A breeze with [`TempFile`](@api/rocket/fs/enum.TempFile.html). Bad form request? Rocket doesn’t call your function! Need to know what went wrong? Use a `data` parameter of `Result`! Want to rerender the form with user input and errors? Use [`Context`](guide/requests/#context)! ''' [[sections]] title = "JSON, always on." code = ''' #[derive(Serialize, Deserialize)] struct Message<'r> { contents: &'r str, } #[put("/", data = "")] fn update(db: &Db, id: Id, msg: Json>) -> Value { if db.contains_key(&id) { db.insert(id, msg.contents); json!({ "status": "ok" }) } else { json!({ "status": "error" }) } } ''' text = ''' Rocket has first-class support for JSON, right out of the box. Simply derive `Deserialize` or `Serialize` to receive or return JSON, respectively. Look familiar? Forms, JSON, and all kinds of body data types work through Rocket’s [`FromData`](@api/rocket/data/trait.FromData.html) trait, Rocket’s approach to deriving types from body data. A `data` route parameter can be _any_ type that implements `FromData`. A value of that type will be deserialized automatically from the incoming request body. You can even implement `FromData` for your own types! ''' ############################################################################### # Bottom features: displayed above the footer. ############################################################################### [[bottom_features]] title = 'Templating' text = "Rocket makes templating a breeze with built-in templating support." image = 'templating-icon' url = 'guide/responses/#templates' button = 'Learn More' color = 'blue' width = '101px' height = '52px' [[bottom_features]] title = 'Cookies' text = "View, add, or remove cookies, with or without encryption, without hassle." image = 'cookies-icon' width = '72px' height = '58px' url = 'guide/requests/#cookies' button = 'Learn More' color = 'fucsia' margin = -6 [[bottom_features]] title = 'WebSockets + Streams' text = "Create and return potentially infinite async streams of data with ease." image = 'streams-icon' url = 'guide/responses/#async-streams' button = 'Learn More' color = 'red' width = '82px' height = '81px' margin = -29 [[bottom_features]] title = 'Config Profiles' text = "Configure your application your way for debug, release, or anything else!" image = 'config-icon' url = 'guide/configuration/#profiles' button = 'Learn More' color = 'yellow' width = '57px' height = '57px' margin = -3 [[bottom_features]] title = 'Type-Checked URIs' text = "Never mistype or forget to update a URI again with Rocket's typed URIs." image = 'pencil-icon' url = 'guide/requests/#private-cookies' button = 'Learn More' color = 'orange' width = '60px' height = '60px' margin = -3 [[bottom_features]] title = 'Structured Middleware' text = "Fairings are Rocket's simpler approach to structured middleware." image = 'ship-icon' url = 'guide/fairings/#fairings' button = 'Learn More' color = 'green' width = '98px' height = '74px' margin = -20 [[bottom_features]] title = 'Database Support' text = "Store data with ease with Rocket's built-in ORM agnostic database support." image = 'query-icon' url = 'guide/state/#databases' button = 'Learn More' color = 'pink' width = '73px' height = '57px' margin = -3 [[bottom_features]] title = 'Testing' text = "Unit and integration test using the comprehensive, built-in testing library." image = 'testing-icon' url = 'guide/testing#testing' button = 'Learn More' color = 'aqua' width = '47px' height = '54px' [[bottom_features]] title = 'Community' text = "Join an extensive community of 20,000+ Rocketeers that love Rocket." image = 'globe' url = 'https://github.com/rwf2/Rocket/network/dependents' button = 'See Dependents' color = 'purple' width = '55px' height = '55px' margin = -1 ############################################################################### # Panels: displayed in a tabbed arrangement. ############################################################################### [[panels]] name = "Routing" checked = true content = ''' Rocket's main task is to route incoming requests to the appropriate request handler using your application's declared routes. Routes are declared using Rocket's _route_ attributes. The attribute describes the requests that match the route. The attribute is placed on top of a function that is the request handler for that route. As an example, consider the simple route below: ```rust #[get("/")] fn index() -> &'static str { "Hello, world!" } ``` This `index` route matches any incoming HTTP `GET` request to `/`, the index. The handler returns a `String`. Rocket automatically converts the string into a well-formed HTTP response that includes the appropriate `Content-Type` and body encoding metadata. ''' [[panels]] name = "Dynamic Params" content = ''' Rocket automatically parses dynamic data in path segments into any desired type. To illustrate, let's use the following route: ```rust #[get("/hello//")] fn hello(name: &str, age: u8) -> String { format!("Hello, {} year old named {}!", age, name) } ``` This `hello` route has two dynamic parameters, identified with angle brackets, declared in the route URI: `` and ``. Rocket maps each parameter to an identically named function argument: `name: &str` and `age: u8`. The dynamic data in the incoming request is parsed automatically into a value of the argument's type. The route is called only when parsing succeeds. Parsing is directed by the [`FromParam`](@api/rocket/request/trait.FromParam.html) trait. Rocket implements `FromParam` for many standard types, including both `&str` and `u8`. You can implement it for your own types, too! ''' [[panels]] name = "Handling Data" content = ''' Rocket can automatically parse body data, too! ```rust #[post("/login", data = "")] fn login(login: Form) -> String { format!("Hello, {}!", login.name) } ``` The dynamic parameter declared in the `data` route attribute parameter again maps to a function argument. Here, `login` maps to `login: Form`. Parsing is again trait-directed, this time by the [`FromData`](@api/rocket/data/trait.FromData.html) trait. The [`Form`](@api/rocket/form/struct.Form.html) type is Rocket's [robust form data parser](@guide/requests/#forms). It automatically parses the request body into the internal type, here `UserLogin`. Other built-in `FromData` types include [`Data`](@api/rocket/struct.Data.html), [`Json`](@api/rocket/serde/json/struct.Json.html), and [`MsgPack`](@api/rocket/serde/msgpack/struct.MsgPack.html). As always, you can implement `FromData` for your own types, too! ''' [[panels]] name = "Request Guards" content = ''' In addition to dynamic path and data parameters, request handlers can also contain a third type of parameter: _request guards_. Request guards aren't declared in the route attribute, and any number of them can appear in the request handler signature. Request guards _protect_ the handler from running unless some set of conditions are met by the incoming request metadata. For instance, if you are writing an API that requires sensitive calls to be accompanied by an API key in the request header, Rocket can protect those calls via a custom `ApiKey` request guard: ```rust #[get("/sensitive")] fn sensitive(key: ApiKey) { ... } ``` `ApiKey` protects the `sensitive` handler from running incorrectly. In order for Rocket to call the `sensitive` handler, the `ApiKey` type needs to be derived through a [`FromRequest`](@api/rocket/request/trait.FromRequest.html) implementation, which in this case, validates the API key header. Request guards are a powerful and unique Rocket concept; they centralize application policy and invariants through types. ''' [[panels]] name = "Responders" content = ''' The return type of a request handler can be any type that implements [`Responder`](@api/rocket/response/trait.Responder.html): ```rust #[get("/")] fn route() -> T { ... } ``` Above, T must implement `Responder`. Rocket implements `Responder` for many of the standard library types including `&str`, `String`, `File`, `Option`, and `Result`. Rocket also implements custom responders such as [`Redirect`](@api/rocket/response/struct.Redirect.html), [`Flash`](@api/rocket/response/struct.Flash.html), and [`Template`](@api/rocket_dyn_templates/struct.Template.html). The task of a `Responder` is to generate a [`Response`](@api/rocket/response/struct.Response.html), if possible. `Responder`s can fail with a status code. When they do, Rocket calls the corresponding error catcher, a `catch` route, which can be declared as follows: ```rust #[catch(404)] fn not_found() -> T { ... } ``` ''' [[panels]] name = "Launching" content = ''' Finally, we get to launch our application! Rocket begins dispatching requests to routes after they've been _mounted_ and the application has been _launched_. These two steps, usually wrtten in a `rocket` function, look like: ```rust #[launch] fn rocket() -> _ { rocket::build().mount("/base", routes![index, another]) } ``` The `mount` call takes a _base_ and a set of routes via the `routes!` macro. The base path (`/base` above) is prepended to the path of every route in the list, effectively namespacing the routes. `#[launch]` creates a `main` function that starts the server. In development, Rocket prints useful information to the console to let you know everything is okay. ```sh 🚀 Rocket has launched from http://127.0.0.1:8000 ``` ''' ############################################################################### # Sponsors ############################################################################### [sponsors.diamond] name = "💎 Diamond" tag = "$500/month" color = "#addcde" height = "110px" [[sponsors.diamond.sponsors]] name = "Kindness" url = "https://kindness.ai" img = "kindness.png" blurb = "Supporting customers with Kindness" width = "110px" [sponsors.gold] name = "💛 Gold" tag = "$250/month" color = "#fffbba" height = "55px" [[sponsors.gold.sponsors]] name = "ohne-makler" url = "https://www.ohne-makler.net/" img = "ohne-makler.svg" width = "173px" [[sponsors.gold.sponsors]] name = "RWF2" url = "https://rwf2.org" img = "rwf2.gif" blurb = "Rocket Web Framework Foundation" width = "55px" [sponsors.bronze] name = "🤎 Bronze" tag = "$50/month" color = "#c7a483" height = "30px" [[sponsors.bronze.sponsors]] name = "1Password" url = "https://1password.com" img = "1password.svg" blurb = "The world’s most-loved password manager" width = "30px"