diff --git a/site/index.toml b/site/index.toml index 7f217357..9a7309eb 100644 --- a/site/index.toml +++ b/site/index.toml @@ -61,8 +61,7 @@ code = ''' ''' text = ''' This is a **complete Rocket application**. It does exactly what you would - expect. If you were to visit **http://localhost:8000/hello/John/58**, you’d - see: + expect. If you were to visit **/hello/John/58**, you’d see: Hello, 58 year old named John! @@ -76,27 +75,26 @@ 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 { - if task.description.is_empty() { - Flash::error(Redirect::to(uri!(home)), "Cannot be empty.") - } else { - Flash::success(Redirect::to(uri!(home)), "Task added.") - } + Flash::success(Redirect::to(uri!(home)), "Task added.") } ''' text = ''' - Handling forms **is simple and easy**. Simply derive `FromForm` for your - structure and let Rocket know which parameter to use. Rocket **parses and - validates** the form request, creates the structure, and calls your function. + 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. - Bad form request? Rocket doesn’t call your function! What if you want to know - if the form was bad? Simple! Change the type of `task` to `Option` or - `Result`! + 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)! File uploads? A + breeze with [`TempFile`](@api/rocket/fs/enum.TempFile.html). ''' [[sections]] @@ -108,7 +106,7 @@ code = ''' } #[put("/", data = "")] - fn update(db: &Db, id: Id, msg: Json>) -> JsonValue { + fn update(db: &Db, id: Id, msg: Json>) -> Value { if db.contains_key(&id) { db.insert(id, msg.contents); json!({ "status": "ok" }) @@ -121,11 +119,12 @@ text = ''' Rocket has first-class support for JSON, right out of the box. Simply derive `Deserialize` or `Serialize` to receive or return JSON, respectively. - Like other important features, JSON works through Rocket’s `FromData` trait, - Rocket’s approach to deriving types from body data. It works like this: - specify a `data` route parameter of any type that implements `FromData`. A - value of that type will then be created automatically from the incoming - request body. Best of all, you can implement `FromData` for your types! + 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! ''' ############################################################################### diff --git a/site/overview.toml b/site/overview.toml index 17839b5a..96b239ae 100644 --- a/site/overview.toml +++ b/site/overview.toml @@ -21,60 +21,61 @@ fn index() -> &'static str { } ``` -This route, named `index`, will match against incoming HTTP `GET` requests to -the `/` path, the index. The request handler returns a string. Rocket will use -the string as the body of a fully formed HTTP response. +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 allows you to interpret segments of a request path dynamically. To -illustrate, let's use the following route: +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: String, age: u8) -> String { +fn hello(name: &str, age: u8) -> String { format!("Hello, {} year old named {}!", age, name) } ``` -The `hello` route above matches two dynamic path segments declared inside -brackets in the path: `` and ``. _Dynamic_ means that the segment can -be _any_ value the end-user desires. +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. -Each dynamic parameter (`name` and `age`) must have a type, here `&str` and -`u8`, respectively. Rocket will attempt to parse the string in the parameter's -position in the path into that type. The route will only be called if parsing -succeeds. To parse the string, Rocket uses the -[FromParam](@api/rocket/request/trait.FromParam.html) trait, -which you can implement for your own types! +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 = ''' -Request body data is handled in a special way in Rocket: via the -[FromData](@api/rocket/data/trait.FromData.html) trait. Any type that implements -`FromData` can be derived from incoming body data. To tell Rocket that you're -expecting request body data, the `data` route argument is used with the name of -the parameter in the request handler: +Rocket can automatically parse body data, too! ```rust -#[post("/login", data = "")] -fn login(user_form: Form) -> String { - format!("Hello, {}!", user_form.name) +#[post("/login", data = "")] +fn login(login: Form) -> String { + format!("Hello, {}!", login.name) } ``` -The `login` route above says that it expects `data` of type `Form` in -the `user_form` parameter. The [Form](@api/rocket/form/struct.Form.html) type -is a built-in Rocket type that knows how to parse web forms into structures. -Rocket will automatically attempt to parse the request body into the `Form` and -call the `login` handler if parsing succeeds. Other built-in `FromData` types -include [`Data`](@api/rocket/struct.Data.html), +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 -[`Flash`](@api/rocket/response/struct.Flash.html). +[`MsgPack`](@api/rocket/serde/msgpack/struct.MsgPack.html). As always, you can +implement `FromData` for your own types, too! ''' [[panels]] @@ -107,7 +108,7 @@ invariants through types. name = "Responders" content = ''' The return type of a request handler can be any type that implements -[Responder](@api/rocket/response/trait.Responder.html): +[`Responder`](@api/rocket/response/trait.Responder.html): ```rust #[get("/")] @@ -117,9 +118,9 @@ 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). +[`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. @@ -135,10 +136,9 @@ fn not_found() -> T { ... } [[panels]] name = "Launching" content = ''' -Launching a Rocket application is the funnest part! For Rocket to begin -dispatching requests to routes, routes need to be _mounted_. After mounting, the -application needs to be _launched_. These two steps, usually done in a `rocket` -function, look like: +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] @@ -147,15 +147,14 @@ fn rocket() -> _ { } ``` -The `mount` call takes a base path 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. This namespaces the routes, allowing for composition. The `#[launch]` -attribute creates a `main` function that starts the server. In development, -Rocket prints useful information to the console to let you know everything is -okay. +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://localhost:8000 +🚀 Rocket has launched from http://127.0.0.1:8000 ``` '''