Add example for FromData.

This commit is contained in:
Sergio Benitez 2016-12-20 18:07:14 -08:00
parent c61e40f5a3
commit f3b7b7db5e
3 changed files with 92 additions and 1 deletions

View File

@ -52,6 +52,88 @@ impl<'a, S, E> IntoOutcome<S, (Status, E), Data> for Result<S, E> {
/// If the `Outcome` is `Forward`, the request will be forwarded to the next
/// matching request. This requires that no data has been read from the `Data`
/// parameter. Note that users can request an `Option<S>` to catch `Forward`s.
///
/// # Example
///
/// Say that you have a custom type, `Person`:
///
/// ```rust
/// struct Person {
/// name: String,
/// age: u16
/// }
/// ```
///
/// `Person` has a custom serialization format, so the built-in `JSON` type
/// doesn't suffice. The format is `<name>:<age>` with `Content-Type:
/// application/x-person`. You'd like to use `Person` as a `FromData` type so
/// that you can retrieve it directly from a client's request body:
///
/// ```rust,ignore
/// #[post("/person", data = "<person>")]
/// fn person(person: Person) -> &'static str {
/// "Saved the new person to the database!"
/// }
/// ```
///
/// A `FromData` implementation allowing this looks like:
///
/// ```rust
/// # #![feature(plugin)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
/// # #[derive(Debug)]
/// # struct Person { name: String, age: u16 }
/// #
/// use std::io::Read;
/// use rocket::{Request, Data, Outcome};
/// use rocket::data::{self, FromData};
/// use rocket::http::{Status, ContentType};
/// use rocket::Outcome::*;
///
/// impl FromData for Person {
/// type Error = String;
///
/// fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
/// // Ensure the content type is correct before opening the data.
/// let person_ct = ContentType::new("application", "x-person");
/// if req.content_type() != person_ct {
/// return Outcome::Forward(data);
/// }
///
/// // Read the data into a String.
/// let mut string = String::new();
/// if let Err(e) = data.open().read_to_string(&mut string) {
/// return Failure((Status::InternalServerError, format!("{:?}", e)));
/// }
///
/// // Split the string into two pieces at ':'.
/// let (name, age) = match string.find(':') {
/// Some(i) => (&string[..i], &string[(i + 1)..]),
/// None => return Failure((Status::BadRequest, "Missing ':'.".into()))
/// };
///
/// // Parse the age.
/// let age: u16 = match age.parse() {
/// Ok(age) => age,
/// Err(e) => return Failure((Status::BadRequest, "Bad age.".into()))
/// };
///
/// // Return successfully.
/// Success(Person {
/// name: name.into(),
/// age: age
/// })
/// }
/// }
/// #
/// # #[post("/person", data = "<person>")]
/// # fn person(person: Person) { }
/// # #[post("/person", data = "<person>")]
/// # fn person2(person: Result<Person, String>) { }
/// # fn main() { }
/// ```
pub trait FromData: Sized {
/// The associated error to be returned when parsing fails.
type Error;

View File

@ -351,6 +351,7 @@ impl<S, E, F> Outcome<S, E, F> {
}
}
#[doc(hidden)]
#[inline(always)]
fn formatting(&self) -> (Color, &'static str) {
match *self {

View File

@ -122,6 +122,10 @@ use response::{Response, Stream};
/// following `Responder` implementation accomplishes this:
///
/// ```rust
/// # #![feature(plugin)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
/// # #[derive(Debug)]
/// # struct Person { name: String, age: u16 }
/// #
@ -133,13 +137,17 @@ use response::{Response, Stream};
/// impl<'r> Responder<'r> for Person {
/// fn respond(self) -> response::Result<'r> {
/// Response::build()
/// .sized_body(Cursor::new(format!("{:?}", self)))
/// .sized_body(Cursor::new(format!("{}:{}", self.name, self.age)))
/// .raw_header("X-Person-Name", self.name)
/// .raw_header("X-Person-Age", self.age.to_string())
/// .header(ContentType::new("application", "x-person"))
/// .ok()
/// }
/// }
///
/// # #[get("/person")]
/// # fn person() -> Person { Person { name: "a".to_string(), age: 20 } }
/// # fn main() { }
/// ```
pub trait Responder<'r> {
/// Returns `Ok` if a `Response` could be generated successfully. Otherwise,