-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
170 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
target | ||
Cargo.lock | ||
target | ||
Cargo.lock | ||
doc/book/_book/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Introduction |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.