Skip to content

Commit

Permalink
Add draft for book
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaka committed Sep 6, 2015
1 parent 0ed8d16 commit 7cd6344
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target
Cargo.lock
target
Cargo.lock
doc/book/_book/
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ after_success:
[ $TRAVIS_PULL_REQUEST = false ] &&
[ $TRAVIS_RUST_VERSION = nightly ] &&
cargo doc &&
npm install gitbook-cli -g &&
gitbook build ./doc/book &&
mv ./doc/book/_book ./target/doc/book &&
git clone https://github.com/davisp/ghp-import &&
./ghp-import/ghp-import target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
Expand Down
1 change: 1 addition & 0 deletions doc/book/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Introduction
9 changes: 9 additions & 0 deletions doc/book/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Summary

This is the summary of my book.

* [Getting started](getting-started.md)
* [Routes](routes.md)
* [Static files](static-files.md)
* [Route parameters](route-params.md)
* [Services](services.md)
30 changes: 30 additions & 0 deletions doc/book/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Getting started

Let's get started with our first website!

Start by running `cargo new my-website`


Add a dependency to `rouille`.


```rust
extern crate rouille;

use rouille::Response;

fn main() {
rouille::start_server("locahost:8000", move |request| {
Response::text("hello world")
})
}
```

The `start_server` function in *rouille* starts listening to the specifiec address and port.
The second parameter must a function or a closure that takes a reference to a `Request` and
returns a `Result`.

Once you wrote that, run `cargo run`. This should download and compile the *rouille* library
and its dependencies, after a few seconds or minutes the server should start. If you go
to [localhost:8000](http://localhost:8000/) when your server is started you should
see `hello world`!
Empty file added doc/book/route-params.md
Empty file.
65 changes: 65 additions & 0 deletions doc/book/routes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Routes

In the previous section, we write a pretty trivial example server:

```rust
extern crate rouille;

use rouille::Response;

fn main() {
rouille::start_server("locahost:8000", move |request| {
Response::text("hello world")
})
}
```

Whenever a client queries a webpage the closure is called and `hello world` is returned.
This means that it doesn't matter whether the client visits `localhost:8000/foo`
or `localhost:8000/bar` because all that is ever returned in `hello world`.

In a real website, we want to handle requests differently depending on the request's URL,
method or headers.

## The `router!` macro

To do so, the *rouille* library provides a macro named `router!` that is every similar to
a `match` expression in Rust.

Let's see it in action:

```rust
#[macro_use]
extern crate rouille;

use rouille::Response;

fn main() {
rouille::start_server("locahost:8000", move |request| {
// dispatching depending on the URL and method
router!(request,
GET (/) => (|| {
Response::text("hello from the root")
}),

GET (/foo) => (|| {
Response::text("hello from /foo")
}),

_ => || Response::text("hello world")
)
})
}
```

Let's see what happens. Whenever a client does a request, our closure is called and the request
is passed to the `router!` macro.

The macro takes each element one by one from top to bottom. It starts by checking whether the
request's URL is `/` and its method `GET`. If it is the case, it executes the content of the
closure after the `=>`. If it's not the case, it then checks for `/foo` and `GET`. If none of
the branches match the request, then the default closure (after `_ =>`) is executed.

Now if you visit `localhost:8000` you should see `hello from the root`. If you visit
`localhost:8000/foo` you should see `hello from /foo`. And if you visit any other address you
should see `hello world`.
59 changes: 59 additions & 0 deletions doc/book/services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Services

Usually a .

## Accessing values from the outside

Accessing

```rust
extern crate rouille;

use rouille::Response;

fn main() {
let some_text = "hello world";

rouille::start_server("locahost:8000", move |request| {
Response::text(some_text)
})
}
```

## Thread safety

However one important thing to note is that **you must handle synchronization**. The
requests-handling function that you pass to `start_server` can be called multiple times
simulatenously, therefore you can't naively modify values from the outside.

For example, let's try to implement a requests counter:

```rust
let mut counter = 0;

rouille::start_server("locahost:8000", move |request| {
counter += 1; // compilation error!
Response::text(format!("Request n#{}", counter))
})
```

If this code compiled, there is a possibility that `counter` is modified twice simultaneously,
which could lead to a bad value being written in `counter`!

Instead the Rust language forces you to use a `Mutex`:

```rust
use std::sync::Mutex;

let counter = Mutex::new(0);

rouille::start_server("locahost:8000", move |request| {
let mut counter = counter.lock().unwrap();
// we now have an exclusive access to `counter`

*counter += 1;
Response::text(format!("Request n#{}", counter))
})
```

Note that in this example we could also have used a `AtomicUsize`.
Empty file added doc/book/static-files.md
Empty file.

0 comments on commit 7cd6344

Please sign in to comment.