Update the guide for async-related API changes.

This commit is contained in:
Jeb Rosen 2020-01-08 08:03:05 -08:00 committed by Sergio Benitez
parent 85761c08e3
commit f2487ccec5
6 changed files with 37 additions and 26 deletions

View File

@ -216,10 +216,11 @@ For the `upload` route, we'll need to `use` a few items:
```rust
use std::io;
use std::path::Path;
use std::path::PathBuf;
use rocket::Data;
use rocket::http::RawStr;
use rocket::response::Debug;
```
The [Data](@api/rocket/data/struct.Data.html) structure is key
@ -279,7 +280,7 @@ fn upload(paste: Data) -> Result<String, Debug<std::io::Error>> {
let url = format!("{host}/{id}\n", host = "http://localhost:8000", id = id);
// Write the paste out to the file and return the URL.
paste.stream_to_file(Path::new(&filename))?;
paste.stream_to_file(PathBuf::from(filename)).await?;
Ok(url)
}
```

View File

@ -412,7 +412,7 @@ imply, a request guard protects a handler from being called erroneously based on
information contained in an incoming request. More specifically, a request guard
is a type that represents an arbitrary validation policy. The validation policy
is implemented through the [`FromRequest`] trait. Every type that implements
`FromRequest` is a request guard.
`FromRequest` (or the related [`FromRequestAsync`]) is a request guard.
Request guards appear as inputs to handlers. An arbitrary number of request
guards can appear as arguments in a route handler. Rocket will automatically
@ -444,6 +444,7 @@ more about request guards and implementing them, see the [`FromRequest`]
documentation.
[`FromRequest`]: @api/rocket/request/trait.FromRequest.html
[`FromRequestAsync`]: @api/rocket/request/trait.FromRequestAsync.html
[`Cookies`]: @api/rocket/http/enum.Cookies.html
### Custom Guards

View File

@ -299,8 +299,8 @@ library. Among these are:
The `Stream` type deserves special attention. When a large amount of data needs
to be sent to the client, it is better to stream the data to the client to avoid
consuming large amounts of memory. Rocket provides the [`Stream`] type, making
this easy. The `Stream` type can be created from any `Read` type. For example,
to stream from a local Unix stream, we might write:
this easy. The `Stream` type can be created from any `AsyncRead` type. For
example, to stream from a local Unix stream, we might write:
```rust
# #[macro_use] extern crate rocket;

View File

@ -203,6 +203,7 @@ request-local state to implement request timing.
[`FromRequest` request-local state]: @api/rocket/request/trait.FromRequest.html#request-local-state
[`Fairing`]: @api/rocket/fairing/trait.Fairing.html#request-local-state
<!-- TODO.async: rewrite? -->
## Databases
Rocket includes built-in, ORM-agnostic support for databases. In particular,

View File

@ -175,22 +175,24 @@ impl Fairing for Counter {
};
}
fn on_response(&self, request: &Request, response: &mut Response) {
// Don't change a successful user's response, ever.
if response.status() != Status::NotFound {
return
}
fn on_response<'a>(&'a self, request: &'a Request<'_>, response: &'a mut Response<'_>) -> BoxFuture<'a, ()> {
Box::pin(async move {
// Don't change a successful user's response, ever.
if response.status() != Status::NotFound {
return
}
// Rewrite the response to return the current counts.
if request.method() == Method::Get && request.uri().path() == "/counts" {
let get_count = self.get.load(Ordering::Relaxed);
let post_count = self.post.load(Ordering::Relaxed);
let body = format!("Get: {}\nPost: {}", get_count, post_count);
// Rewrite the response to return the current counts.
if request.method() == Method::Get && request.uri().path() == "/counts" {
let get_count = self.get.load(Ordering::Relaxed);
let post_count = self.post.load(Ordering::Relaxed);
let body = format!("Get: {}\nPost: {}", get_count, post_count);
response.set_status(Status::Ok);
response.set_header(ContentType::Plain);
response.set_sized_body(Cursor::new(body));
}
response.set_status(Status::Ok);
response.set_header(ContentType::Plain);
response.set_sized_body(Cursor::new(body));
}
})
}
}
```
@ -220,9 +222,9 @@ rocket::ignite()
.attach(AdHoc::on_launch("Launch Printer", |_| {
println!("Rocket is about to launch! Exciting! Here we go...");
}))
.attach(AdHoc::on_request("Put Rewriter", |req, _| {
.attach(AdHoc::on_request("Put Rewriter", |req, _| Box::pin(async move {
req.set_method(Method::Put);
}));
})));
```
[`AdHoc`]: @api/rocket/fairing/struct.AdHoc.html

View File

@ -103,7 +103,7 @@ use rocket::http::{ContentType, Status};
let rocket = rocket::ignite().mount("/", routes![hello]);
let client = Client::new(rocket).expect("valid rocket instance");
let mut response = client.get("/").dispatch();
let mut response = client.get("/").dispatch().await;
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::Plain));
@ -167,7 +167,13 @@ You can also move the body of the `test` module into its own file, say
### Testing
To test our "Hello, world!" application, we first create a `Client` for our
First, note the `#[rocket::async_test]` attribute. Rust does not support `async
fn` for tests, so an asynchronous runtime needs to be set up. In most
applications this is done by `launch()`, but we are deliberately not calling
that in tests! Instead, we use `#[rocket::async_test]`, which runs the test
inside a runtime.
To test our "Hello, world!" application, we create a `Client` for our
`Rocket` instance. It's okay to use methods like `expect` and `unwrap` during
testing: we _want_ our tests to panic when something goes wrong.
@ -211,7 +217,7 @@ use rocket::http::{ContentType, Status};
# let mut response = client.get("/").dispatch();
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.body_string(), Some("Hello, world!".into()));
assert_eq!(response.body_string().await, Some("Hello, world!".into()));
```
That's it! Altogether, this looks like:
@ -242,9 +248,9 @@ mod test {
# */ pub
fn hello_world() {
let client = Client::new(rocket()).expect("valid rocket instance");
let mut response = client.get("/").dispatch();
let mut response = client.get("/").dispatch().await;
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.body_string(), Some("Hello, world!".into()));
assert_eq!(response.body_string().await, Some("Hello, world!".into()));
}
}