From 15fe6ec8d0f2eeba3fc1ac146cba073f39b08fd1 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Sun, 13 Nov 2016 19:01:09 -0800 Subject: [PATCH] Remove stale documents. Merge existing docs into one guide. --- docs/{overview.md => guide.md} | 200 ++++++++++++++++++++++++-- docs/intro.md | 252 --------------------------------- docs/overview-old.md | 245 -------------------------------- 3 files changed, 190 insertions(+), 507 deletions(-) rename docs/{overview.md => guide.md} (68%) delete mode 100644 docs/intro.md delete mode 100644 docs/overview-old.md diff --git a/docs/overview.md b/docs/guide.md similarity index 68% rename from docs/overview.md rename to docs/guide.md index 87ddf07d..641381b8 100644 --- a/docs/overview.md +++ b/docs/guide.md @@ -1,18 +1,181 @@ -# Overview +Welcome to Rocket! This is the official guide. It is designed to serve as a +starting point as a well as reference. This guide is conversational. For concise +and purely technical documentation, see the [API documentation](/API). -A quick glance at what makes Rocket special. +------------------------------------------------------------------------------- + +# IDEA + +HAVE THIS GUIDE SERVE AS A REFERENCE AS WELL BY MARKING PIECES OF THIS GUIDE AS +'GUIDE ONLY' AND OMITTING THOSE SECTIONS WHEN SOMEONE WANTS A REFERENCE ONLY. IT +WOULD BE NEAT IF THERE WAS A LITTLE JAVASCRIPT BUTTON THAT JUST HID THE GUIDE +PARTS. + +# Guide + +Hello! By now you've gleaned that Rocket is a web framework for Rust. You also +know that it aims to be fast, easy, and flexible. It also aims to be _fun_, and +it accomplishes this by ensuring that you write as little code as needed to +accomplish your task. This guide is meant to introduce you to the core, +intermediate, and advanced concepts of Rocket. After reading this guide, you +should find yourself being _very_ productive with Rocket. + +## Audience + +Readers of this guide are assumed to have a good grasp of the Rust programming +language. Readers new to Rust are encourage to read through the [Rust +Book](https://doc.rust-lang.org/book/). This guide also assumes a basic +understanding of web application fundamentals and HTTP. + +# Foreword + +Rocket's philosophy is that a function declaration should contain all of the +necessary information to process a request. This immediately prohibits APIs +where request state is retrieved from a global context. As a result of the +locality of information, request handling is _self contained_ in Rocket: +handlers are regular functions that can be called by other code. + +Rocket also believes that all request handling information should be _typed_. +Because the web and HTTP are themselves untyped (or _stringly_ typed, as some +call it), this means that something or someone has to convert strings to native +types. Rocket does this for you with zero programming overhead. + +These two core philosophies dictate Rocket's interface, and you will find the +ideas embedded in Rocket's core features. But, enough with the boring diatribe. +Let's get to know Rocket. + +# Quick Start + +The absolute fastest way to start experimenting with Rocket is to clone the +Rocket repository and run the included examples. For instance, the following set +of commands runs the `hello_world` example: + +```sh +git clone https://github.com/SergioBenitez/rocket +cd rocket/examples/hello_world +cargo run +``` + +There are numerous examples in `rocket/examples`, all of which can be run with +Cargo by using `cargo run`. Note that Rocket requires the latest Rust nightly. + +# Getting Started + +Let's create and run our first Rocket application. We'll ensure we have a +compatible version of Rust, create a new Cargo project that uses Rocket, and +then run the project. + +## Rust + +Rocket makes heavy use of Rust's syntax extensions. Because syntax extension +don't yet have a stable compiler API, we'll need to use a nightly version of +Rust with Rocket. If you already have a working installation of the latest Rust +nightly, feel free to skip this section. + +To install a nightly version of Rust, we recommend using `rustup`. Install +`rustup` by following the instructions on [their website](https://rustup.rs/). +Once `rustup` is installed, configure Rust nightly as your default toolchain by +running the command: + +```sh +rustup default nightly +``` + +If you prefer, once we setup a project directory in the following section, you +can use per-directory defaults to use the nightly version _only_ for your Rocket +project by running the following command in the directory: + +```sh +rustup override set nightly +``` + +Rocket requires the latest version of Rust nightly. If your Rocket application +suddently stops building, ensure you're using the latest version of Rust by +updating: + +```sh +rustup update +``` + +## Creating a Rocket Project + +Start by creating a new binary-based Cargo project and changing into the new +directory: + +```sh +cargo new hello-rocket --bin +cd hello-rocket +``` + +Now, add Rocket and its code generation facilities to your project by ensuring +your `Cargo.toml` file contains the following dependencies: + +``` +[dependencies] +rocket = "*" +rocket_codegen = "*" +``` + +Build the project now to ensure your Rust version is compatible with the latest +Rocket version: + +```sh +cargo build +``` + +Modify `src/main.rs` so that it contains the code for the Rocket `Hello, world!` +program, which we reproduce below: + +```rust +#![feature(plugin)] +#![plugin(rocket_codegen)] + +extern crate rocket; + +#[get("/")] +fn hello() -> &'static str { + "Hello, world!" +} + +fn main() { + rocket::ignite().mount("/hello", routes![hello]).launch(); +} +``` + +Run the program by using `cargo run`. You should see the following in your +terminal: + +```sh +πŸ”§ Configured for development. + => listening: localhost:8000 + => logging: Normal + => session key: false +πŸ›° Mounting '/hello': + => GET /hello/ +πŸš€ Rocket has launched from localhost:8000... +``` + +Finally, visit `http://localhost:8000` to see your first Rocket application in +action. # Introduction -This overview is a concise introduction to Rocket. There's also a [full, -detailed guide](guide). If you want to get started immediately, see -[quickstart](guide/quickstart) or the [getting started -guide](guide/getting_started). Otherwise, welcome! +Rocket provides a focused number of core primitives to build web servers and +applications with Rust: the rest is up to you. In short, Rocket provides +routing, pre-processing of requests, and post-processing of responses. Your +application code fills the gap between pre-processing and post-processing. -Rocket makes writing web applications easy, fast, and fun. It is Rocket's goal -to have you write as little code as necessary to accomplish your goal. In -practice, this means that your code will be free of boilerplate and that the -common tasks will be handled for you. +Rocket _does not_ force decisions on you. Templates, serialization, sessions, +and just about everything else are all pluggable, optional components. While +Rocket has official support and libraries for each of these, they are completely +optional to use, and writing your own versions of these is not only possible, +but straightforward. These components feel like first-class citizens. + +If you'd like, you can think of Rocket as being a more flexible, friendly medley +of [Rails](rubyonrails.org), [Flask](http://flask.pocoo.org/), +[Bottle](http://bottlepy.org/docs/dev/index.html), and +[Yesod](http://www.yesodweb.com/), except without all of the bloat. We prefer to +think of Rocket as something new. # Routes and Handlers @@ -41,6 +204,23 @@ fn world() -> &'static str { This declares the `world` route which matches against the static path `"/world"` for incoming `GET` requests. + + +Rocket route attributes have the following grammar: + +```ebnf +route := METHOD '(' path, kv_param* ')' + +path := PATH + | 'path' = PATH + +kv_param := 'rank' = INTEGER + | 'form' = STRING + | 'format' = STRING +``` + + + ## Mounting Before Rocket dispatches requests to a route, the route needs to be _mounted_ on diff --git a/docs/intro.md b/docs/intro.md deleted file mode 100644 index e16f020d..00000000 --- a/docs/intro.md +++ /dev/null @@ -1,252 +0,0 @@ -Welcome to Rocket! This is the official guide. It is designed to serve as a -starting point as a well as reference. This guide is conversational. For concise -and purely technical documentation, see the [API documentation](/API). - -------------------------------------------------------------------------------- - -# IDEA - -HAVE THIS GUIDE SERVE AS A REFERENCE AS WELL BY MARKING PIECES OF THIS GUIDE AS -'GUIDE ONLY' AND OMITTING THOSE SECTIONS WHEN SOMEONE WANTS A REFERENCE ONLY. IT -WOULD BE NEAT IF THERE WAS A LITTLE JAVASCRIPT BUTTON THAT JUST HID THE GUIDE -PARTS. - -# Guide - -Hello! By now you've gleaned that Rocket is a web framework for Rust. You also -know that it aims to be fast, easy, and flexible. It also aims to be _fun_, and -it accomplishes this by ensuring that you write as little code as needed to -accomplish your task. This guide is meant to introduce you to the core, -intermediate, and advanced concepts of Rocket. After reading this guide, you -should find yourself being _very_ productive with Rocket. - -## Audience - -Readers of this guide are assumed to have a good grasp of the Rust programming -language. Readers new to Rust are encourage to read through the [Rust -Book](https://doc.rust-lang.org/book/). This guide also assumes a basic -understanding of web application fundamentals and HTTP. - -# Foreword - -Rocket's philosophy is that a function declaration should contain all of the -necessary information to process a request. This immediately prohibits APIs -where request state is retrieved from a global context. As a result of the -locality of information, request handling is _self contained_ in Rocket: -handlers are regular functions that can be called by other code. - -Rocket also believes that all request handling information should be _typed_. -Because the web and HTTP are themselves untyped (or _stringly_ typed, as some -call it), this means that something or someone has to convert strings to native -types. Rocket does this for you with zero programming overhead. - -These two core philosophies dictate Rocket's interface, and you will find the -ideas embedded in Rocket's core features. But, enough with the boring diatribe. -Let's get to know Rocket. - -# Quick Start - -The absolute fastest way to start experimenting with Rocket is to clone the -Rocket repository and run the included examples. For instance, the following set -of commands runs the `hello_world` example: - -```sh -git clone https://github.com/SergioBenitez/rocket -cd rocket/examples/hello_world -cargo run -``` - -There are numerous examples in `rocket/examples`, all of which can be run with -Cargo by using `cargo run`. Note that Rocket requires the latest Rust nightly. - -# Getting Started - -Let's create and run our first Rocket application. We'll ensure we have a -compatible version of Rust, create a new Cargo project that uses Rocket, and -then run the project. - -## Rust - -Rocket makes heavy use of Rust's syntax extensions. Because syntax extension -don't yet have a stable compiler API, we'll need to use a nightly version of -Rust with Rocket. If you already have a working installation of the latest Rust -nightly, feel free to skip this section. - -To install a nightly version of Rust, we recommend using `rustup`. Install -`rustup` by following the instructions on [their website](https://rustup.rs/). -Once `rustup` is installed, configure Rust nightly as your default toolchain by -running the command: - -```sh -rustup default nightly -``` - -If you prefer, once we setup a project directory in the following section, you -can use per-directory defaults to use the nightly version _only_ for your Rocket -project by running the following command in the directory: - -```sh -rustup override set nightly -``` - -Rocket requires the latest version of Rust nightly. If your Rocket application -suddently stops building, ensure you're using the latest version of Rust by -updating: - -```sh -rustup update -``` - -## Creating a Rocket Project - -Start by creating a new binary-based Cargo project and changing into the new -directory: - -```sh -cargo new hello-rocket --bin -cd hello-rocket -``` - -Now, add Rocket and its code generation facilities to your project by ensuring -your `Cargo.toml` file contains the following dependencies: - -``` -[dependencies] -rocket = "*" -rocket_codegen = "*" -``` - -Build the project now to ensure your Rust version is compatible with the latest -Rocket version: - -```sh -cargo build -``` - -Modify `src/main.rs` so that it contains the code for the Rocket `Hello, world!` -program, which we reproduce below: - -```rust -#![feature(plugin)] -#![plugin(rocket_codegen)] - -extern crate rocket; - -#[get("/")] -fn hello() -> &'static str { - "Hello, world!" -} - -fn main() { - rocket::ignite().mount("/hello", routes![hello]).launch(); -} -``` - -Run the program by using `cargo run`. You should see the following in your -terminal: - -```sh -πŸ”§ Configured for development. - => listening: localhost:8000 - => logging: Normal - => session key: false -πŸ›° Mounting '/hello': - => GET /hello/ -πŸš€ Rocket has launched from localhost:8000... -``` - -Finally, visit `http://localhost:8000` to see your first Rocket application in -action. - -# Introduction - -Rocket provides a focused number of core primitives to build web servers and -applications with Rust: the rest is up to you. In short, Rocket provides -routing, pre-processing of requests, and post-processing of responses. Your -application code fills the gap between pre-processing and post-processing. - -Rocket _does not_ force decisions on you. Templates, serialization, sessions, -and just about everything else are all pluggable, optional components. While -Rocket has official support and libraries for each of these, they are completely -optional to use, and writing your own versions of these is not only possible, -but straightforward. These components feel like first-class citizens. - -If you'd like, you can think of Rocket as being a more flexible, friendly medley -of [Rails](rubyonrails.org), [Flask](http://flask.pocoo.org/), -[Bottle](http://bottlepy.org/docs/dev/index.html), and -[Yesod](http://www.yesodweb.com/), except without all of the bloat. We prefer to -think of Rocket as something new. - -# From Request to Response - -This section of the guide provides a grand overview of Rocket by examining a -simple application. Let's begin. - -```rust -#![feature(plugin)] -#![plugin(rocket_codegen)] - -extern crate rocket; - -#[get("hi//")] -fn hello(name: &str, age: i8) -> String { - format!("Hello, {} year old named {}!", age, name) -} - -#[get("bye/")] -fn goodbye(name: &str) -> String { - format!("Hello, {} year old named {}!", age, name) -} - -#[error(404)] -fn not_found() -> &'static str { - "Sorry, I don't know what you're looking for." -} - -fn main() { - rocket::ignite() - .mount("/", routes![hello, goodbye]) - .catch(errors![not_found]) - .launch(); -} -``` - -# Routing - -The task of a web application is to handle incoming requests by returning an -appropriate response. The code that handles the request is called a _request -handler_. Requests are made to specific paths, URIs, and with a specific intent, -declared via an HTTP method, in mind. The code that determines which request -handler should be invoked for a given request is called a _request router_, or -just _router_. - -In Rocket, request handlers are regular functions, and you tell Rocket's router -which requests are intended for a given handler through an annotation, or -attribute, on that function. We call the combination of a handler and its -attribute a _route_. - -The code below is one of the simplest routes we can write in Rocket: - -```rust -#[get("/hello")] -fn hello() -> &'static str { - "Hello, world!" -} -``` - -As you might expect, the code declares that the `hello` function is the handler -for any `GET` requests to the `/hello` path, and that the response to the -request is of type `&'static str` whose value is `Hello, world!`. - -Rocket route attributes have the following grammar: - -```ebnf -route := METHOD '(' path, kv_param* ')' - -path := PATH - | 'path' = PATH - -kv_param := 'rank' = INTEGER - | 'form' = STRING - | 'format' = STRING -``` diff --git a/docs/overview-old.md b/docs/overview-old.md deleted file mode 100644 index be85b4f1..00000000 --- a/docs/overview-old.md +++ /dev/null @@ -1,245 +0,0 @@ -# Overview - -A quick glance at what makes Rocket special. - -# Introduction - -This overview is a concise introduction to Rocket. There's also a [full, -detailed guide](guide). If you want to get started immediately, see -[quickstart](guide/quickstart) or the [getting started -guide](guide/getting_started). Otherwise, welcome! - -Rocket makes writing web applications easy, fast, and fun. Below is a complete -Rocket application. In fact, it's [one of many](thisexample) complete, runnable -examples in [Rocket's git repository](github). Can you figure out what it does? - -```rust -#![feature(plugin)] -#![plugin(rocket_codegen)] - -extern crate rocket; - -#[get("//")] -fn hello(name: &str, age: u8) -> String { - format!("Hello, {} year old named {}!", age, name) -} - -fn main() { - rocket::ignite() - .mount("/hello", routes![hello]) - .launch(); -} -``` - -If you were to run this application, your console would show: - -```sh -πŸ”§ Configured for development. - => listening: localhost:8000 - => logging: Normal - => session key: false -πŸ›° Mounting '/hello': - => GET /hello// -πŸš€ Rocket has launched from localhost:8000... -``` - -Here's a quick summary of what it does: first, on lines 7 - 10, it declares the -`hello` route to `GET //`, which returns a `String` formatted with -`name` and `age` from the dynamic path. Then, in the `main` function, it creates -a new `Rocket` instance, mounts the `hello` route at `"/hello"`, and launches -the application. - -That's it! Let's break this down. - -We'll start with lines 1 and 2. Rocket depends on the latest version Rust -nightly; it makes extensive use of Rust's code generation facilities through -compiler plugins. Plugins are still experimental, so we have to tell Rust that -we're okay with that by writing `#![feature(plugin)]`. We also have to tell the -compiler to use Rocket's code generation crate during compilation with -`#![plugin(rocket_codegen)]`. Lines 4 and 5 bring `rocket::Rocket` into the -namespace. - -# Routes - -The fun begins on line 7, where the `hello` route and request handler are -declared. - -Rocket applications are composed primarily of request handlers and routes. A -_request handler_ is a function that takes an arbitrary number of arguments and -returns a response. A _route_ is a combination of: - - * A set of parameters to match an incoming request against. - * A request handler to process the request and return a response. - -The set of parameters to match against includes static paths, dynamic paths, -path segments, forms, query strings, and request format specifiers. Rocket uses -Rust attributes, which look like function decorators in other languages, to make -declaring routes easy. Routes are declares by annotating a function with the set -of parameters to match against. A complete route declaration looks like: - -```rust -#[get("/index")] -fn index() -> &str { "Hello, World!" } -``` - -You can also use `put`, `post`, `delete`, and `patch` in place of `get`. - -## Dynamic Paths - -The `hello` route declaration beginning on line 7 of our example applications -tells Rocket that the `hello` function will handle HTTP `GET` requests to the -`/` path. The handler uses `name` and `age` from the path to format -and return a `String` to the user. Here are lines 7 - 10 again: - -```rust -#[get("//")] -fn hello(name: &str, age: u8) -> String { - format!("Hello, {} year old named {}!", age, name) -} -``` - -The `` and `` parts of the path are _dynamic_: the actual values for -these segments won't be known until someone visits a matching URL. For example, -if someone visit `Mike/21`, `` will be `"Mike"`, and `` will be `21`. -If someone else visits `Bob/91`, `` and `` will be `"Bob"` and -`91`, respectively. Rocket automatically parses dynamic path segments and -passes them to the request handler in variables with matching names. This -means that `name` and `age` can be used immediately in the handler - no -parsing, no checking. - -But wait: what happens if someone goes to a URL with an `` that isn't a -valid `u8`? In that case, Rocket doesn't call the handler. Instead, it -_forwards_ the request to the next matching route, if any, and ultimately -returns a `404` if all of them fail. If you want to know if the user passed in a -bad ``, simply use a `Result` or an `Option` type for `age` -instead. For more details on routing, route collisions, and much more see the -[routing](guide/routing) chapter of the guide. - -Oh, one more thing before we move on! Notice how dynamic path parameters can be -of different types? Actually, path parameters can be of _any_ type, as long as -that type implements Rocket's `FromParam` trait. Rocket uses the `FromParam` -implementation to parse and validate the parameter for you automatically. We've -implemented `FromParam` for plenty of types in the standard library. See the -[FromParam](docs) documentation for more. - -## Mounting - -Now that we understand the `hello` route, let's move on to lines 13 - 14. Before -Rocket dispatches requests to a route, the route needs to be _mounted_. And -before we can mount a route, we need an instance of `Rocket`. - -Mounting a route is like namespacing it. Routes can be mounted any number of -times. Mounting happens with the `mount` method on a `Rocket` instance, which -itself is created with the `ignite()` static method. The `mount` method takes a -list of route handlers given inside of the `route!` macro. The `route!` macro -ties Rocket's code generation to your application. If you'd like to learn more -about the `route!` macro, see the [internals guide](guide/internals). - -Let's look at lines 13 - 14 again, which we reproduce below: - -```rust -rocket::ignite() - .mount(β€œ/hello”, routes![hello]) -``` - -Line 13 creates the new `Rocket` instance, and line 14 mounts the `hello` route -at the `"/hello"` path. This makes the `hello` handler available at -`/hello//`. Notice how the mounting path is prepended to the route's -path. There's a ton more information about [mounting in the -guide](/guides/mounting). - -## Launching - -Now that the route is declared and mounted, the application is ready to launch! -To launch an application and have Rocket start listening for and dispatching -requests, simply call `launch` on the Rocket instance where routes are mounted. -This happens on line 14. Here it is again: - -``` -rocket.launch() -``` - -Again, running our full example will show the following in the console: - -```sh -πŸ›° Mounting '/hello': - => GET /hello// -πŸš€ Rocket has launched from localhost:8000... -``` - -If you visit `http://localhost:8000/hello/Mike/21`, you'll see "Hello, 21 year -old named Mike!". If you have the example running, try visiting other valid and -invalid paths and see what happens! This example's complete crate, ready to -`cargo run`, can be found at -[Github](https://github.com/SergioBenitez/Rocket/tree/master/examples/hello_world). - -# Requests - -There's a lot more we can do with requests. The [requests](guide/requests) -chapter of the guide talks about requests in details. We'll give you a short -overview of some of the more important and useful features here. - -## Forms and Queries - -Handling forms and query parameters couldn't be easier: declare a form or query -parameter in the route attribute and handler, then ensure that its type -implements (the automatically derivable) `FromForm`. - -Form parameters are declared by adding `form = ""` to the route -attribute. Say your application is processing a form submission for a new todo -`Task`. The form contains two fields: `complete`, a checkbox, and `description`, -a text field. You can easily handle the form request in Rocket as follows: - -```rust -#[derive(FromForm)] -struct Task { - description: String, - complete: bool -} - -#[post("/todo", form = "")] -fn new(task: Task) -> String { - ... -} -``` - -If you change your mind and want to use query strings for the form instead, -simple declare `` as a query parameter as follows: - -```rust -#[get("/todo?")] -fn new(task: Task) -> String { - ... -} -``` - -If the form request is invalid according to the form's type, the handler doesn't -get called. Just like in path parameters, you can use `Option` or `Result` in -form structure fields to be notified of parsing errors. You can also easily -define your own types to validate forms and queries against. For more details, -see the [forms](guide/forms) and [queries](guide/queries) chapters of the guide. - -## Guards - -In addition to `FromParam` types, you can include any number of types that -implement the `FromRequest` trait in handler arguments. For example, to -retrieve cookies from a request, you can use a parameter of `&Cookie` type in a -request handler: - -```rust -#[get("/hello")] -fn hello(cookies: &Cookies) -> .. -``` - -## JSON - -# Responses - -## Responder - -## Templates - -## JSON - -# What's next? -