mirror of https://github.com/rwf2/Rocket.git
Document Responder. Further document Flash. Implement Debug for most Responder types.
This commit is contained in:
parent
7beec53889
commit
129268506e
|
@ -26,7 +26,7 @@ impl<'a, S, E> IntoOutcome<S, (StatusCode, E), Data> for Result<S, E> {
|
|||
/// fn submit(var: T) -> ... { ... }
|
||||
/// ```
|
||||
///
|
||||
/// In this example, `T` can be any type that implements `FromData.`
|
||||
/// In this example, `T` can be any type that implements `FromData`.
|
||||
///
|
||||
/// # Outcomes
|
||||
///
|
||||
|
|
|
@ -3,6 +3,7 @@ use http::hyper::{header, FreshHyperResponse};
|
|||
use http::mime::{Mime, TopLevel, SubLevel};
|
||||
use http::ContentType;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Content<T: Responder>(pub ContentType, pub T);
|
||||
|
||||
impl<T: Responder> Responder for Content<T> {
|
||||
|
@ -14,6 +15,7 @@ impl<T: Responder> Responder for Content<T> {
|
|||
|
||||
macro_rules! impl_data_type_responder {
|
||||
($name:ident: $top:ident/$sub:ident) => (
|
||||
#[derive(Debug)]
|
||||
pub struct $name<T: Responder>(pub T);
|
||||
|
||||
impl<T: Responder> Responder for $name<T> {
|
||||
|
|
|
@ -5,10 +5,11 @@ use response::{self, Responder};
|
|||
use request::{self, Request, FromRequest};
|
||||
use http::hyper::{HyperSetCookie, HyperCookiePair, FreshHyperResponse};
|
||||
|
||||
// The name of the actual flash cookie.
|
||||
const FLASH_COOKIE_NAME: &'static str = "_flash";
|
||||
|
||||
/// Sets a "flash" cookies that will be removed the next time it is accessed.
|
||||
/// The anologous type on the request side is
|
||||
/// Sets a "flash" cookie that will be removed when it is accessed. The
|
||||
/// anologous request type is
|
||||
/// [FlashMessage](/rocket/request/type.FlashMessage.html).
|
||||
///
|
||||
/// This type makes it easy to send messages across requests. It is typically
|
||||
|
@ -30,12 +31,56 @@ const FLASH_COOKIE_NAME: &'static str = "_flash";
|
|||
/// [FlashMessage](/rocket/request/type.FlashMessage.html) type and the
|
||||
/// [name](#method.name) and [msg](#method.msg) methods.
|
||||
///
|
||||
/// # Responder
|
||||
/// # Response
|
||||
///
|
||||
/// The `Responder` implementation for `Flash` sets the message cookie and then
|
||||
/// uses the passed in responder `res` to complete the response. In other words,
|
||||
/// it simply sets a cookie and delagates the rest of the response handling to
|
||||
/// the wrapped responder.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// The following complete Rocket application illustrates the use of a `Flash`
|
||||
/// message on both the request and response sides.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![feature(plugin)]
|
||||
/// # #![plugin(rocket_codegen)]
|
||||
/// #
|
||||
/// # extern crate rocket;
|
||||
/// #
|
||||
/// use rocket::response::{Flash, Redirect};
|
||||
/// use rocket::request::FlashMessage;
|
||||
///
|
||||
/// #[post("/login/<name>")]
|
||||
/// fn login(name: &str) -> Result<&'static str, Flash<Redirect>> {
|
||||
/// if name == "special_user" {
|
||||
/// Ok("Hello, special user!")
|
||||
/// } else {
|
||||
/// Err(Flash::error(Redirect::to("/"), "Invalid username."))
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[get("/")]
|
||||
/// fn index(flash: Option<FlashMessage>) -> String {
|
||||
/// flash.map(|msg| format!("{}: {}", msg.name(), msg.msg()))
|
||||
/// .unwrap_or_else(|| "Welcome!".to_string())
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// # if false { // We don't actually want to launch the server in an example.
|
||||
/// rocket::ignite().mount("/", routes![login, index]).launch()
|
||||
/// # }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// On the response side (in `login`), a `Flash` error message is set if some
|
||||
/// fictional authentication failed, and the user is redirected to `"/"`. On the
|
||||
/// request side (in `index`), the handler emits the flash message if there is
|
||||
/// one and otherwise emits a standard welcome message. Note that if the user
|
||||
/// were to refresh the index page after viewing a flash message, the user would
|
||||
/// receive the standard welcome message.
|
||||
#[derive(Debug)]
|
||||
pub struct Flash<R> {
|
||||
name: String,
|
||||
message: String,
|
||||
|
@ -124,6 +169,10 @@ impl<R: Responder> Flash<R> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the message cookie and then uses the wrapped responder to complete the
|
||||
/// response. In other words, simply sets a cookie and delagates the rest of the
|
||||
/// response handling to the wrapped responder. As a result, the `Outcome` of
|
||||
/// the response is the `Outcome` of the wrapped `Responder`.
|
||||
impl<R: Responder> Responder for Flash<R> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> response::Outcome<'b> {
|
||||
trace_!("Flash: setting message: {}:{}", self.name, self.message);
|
||||
|
@ -133,6 +182,7 @@ impl<R: Responder> Responder for Flash<R> {
|
|||
}
|
||||
|
||||
impl Flash<()> {
|
||||
/// Constructs a new message with the given name and message.
|
||||
fn named(name: &str, msg: &str) -> Flash<()> {
|
||||
Flash {
|
||||
name: name.to_string(),
|
||||
|
@ -152,7 +202,11 @@ impl Flash<()> {
|
|||
}
|
||||
}
|
||||
|
||||
// This is Type-Aliased in Request.
|
||||
/// Retrieves a flash message from a flash cookie and deletes the flash cookie.
|
||||
/// If there is no flash cookie, an empty `Err` is returned.
|
||||
///
|
||||
/// The suggested use is through an `Option` and the `FlashMessage` type alias
|
||||
/// in `request`: `Option<FlashMessage>`.
|
||||
impl<'r> FromRequest<'r> for Flash<()> {
|
||||
type Error = ();
|
||||
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
//! Types and traits to build and send responses.
|
||||
//!
|
||||
//! The return type of a Rocket handler can be any type that implements the
|
||||
//! [Responder](trait.Responder.html) trait. This module contains several useful
|
||||
//! types that implement this trait.
|
||||
//! [Responder](trait.Responder.html) trait. This module contains several such
|
||||
//! types.
|
||||
//!
|
||||
//! # Composing
|
||||
//!
|
||||
//! Many of the built-in `Responder` types _chain_ responses: they take in
|
||||
//! another `Responder` and simply add, remove, or change information in the
|
||||
//! response. In other words, many `Responder` types are built to compose well.
|
||||
//! As a result, you'll often have types of the form `A<B<C>>` consisting of
|
||||
//! three `Responder`s `A`, `B`, and `C`. This is normal and encouraged as the
|
||||
//! type names typically illustrate the intended response.
|
||||
|
||||
mod responder;
|
||||
mod redirect;
|
||||
|
|
|
@ -19,7 +19,69 @@ impl<'a, T, E> IntoOutcome<(), (), (StatusCode, FreshHyperResponse<'a>)> for Res
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by types that send a response to clients.
|
||||
///
|
||||
/// Types that implement this trait can be used as the return type of a handler,
|
||||
/// as illustrated below:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// #[get("/")]
|
||||
/// fn index() -> T { ... }
|
||||
/// ```
|
||||
///
|
||||
/// In this example, `T` can be any type that implements `Responder`.
|
||||
///
|
||||
/// # Outcomes
|
||||
///
|
||||
/// The returned [Outcome](/rocket/outcome/index.html) of a `respond` call
|
||||
/// determines how the response will be processed, if at all.
|
||||
///
|
||||
/// * **Success**
|
||||
///
|
||||
/// An `Outcome` of `Success` indicates that the responder was successful in
|
||||
/// sending the response to the client. No further processing will occur as a
|
||||
/// result.
|
||||
///
|
||||
/// * **Failure**
|
||||
///
|
||||
/// An `Outcome` of `Failure` indicates that the responder failed after
|
||||
/// beginning a response. The response is incomplete, and there is no way to
|
||||
/// salvage the response. No further processing will occur.
|
||||
///
|
||||
/// * **Forward**(StatusCode, FreshHyperResponse<'a>)
|
||||
///
|
||||
/// If the `Outcome` is `Forward`, the response will be forwarded to the
|
||||
/// designated error [Catcher](/rocket/struct.Catcher.html) for the given
|
||||
/// `StatusCode`. This requires that a response wasn't started and thus is
|
||||
/// still fresh.
|
||||
///
|
||||
/// # Implementation Tips
|
||||
///
|
||||
/// This section describes a few best practices to take into account when
|
||||
/// implementing `Responder`.
|
||||
///
|
||||
/// ## Debug
|
||||
///
|
||||
/// A type implementing `Responder` should implement the `Debug` trait when
|
||||
/// possible. This is because the `Responder` implementation for `Result`
|
||||
/// requires its `Err` type to implement `Debug`. Therefore, a type implementing
|
||||
/// `Debug` can more easily be composed.
|
||||
///
|
||||
/// ## Check Before Changing
|
||||
///
|
||||
/// Unless a given type is explicitly designed to change some information in
|
||||
/// ther esponse, it should first _check_ that some information hasn't been set
|
||||
/// before _changing_ that information. For example, before setting the
|
||||
/// `Content-Type` header of a response, first check that the header hasn't been
|
||||
/// set.
|
||||
pub trait Responder {
|
||||
/// Attempts to write a response to `res`.
|
||||
///
|
||||
/// If writing the response successfully completes, an outcome of `Success`
|
||||
/// is returned. If writing the response begins but fails, an outcome of
|
||||
/// `Failure` is returned. If writing a response fails before writing
|
||||
/// anything out, an outcome of `Forward` can be returned, which causes the
|
||||
/// response to be written by the appropriate error catcher instead.
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a>;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::io::{Read, Write, ErrorKind};
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
use response::{Responder, Outcome};
|
||||
use http::hyper::FreshHyperResponse;
|
||||
|
@ -26,6 +27,12 @@ impl<T: Read> Stream<T> {
|
|||
// }
|
||||
}
|
||||
|
||||
impl<T: Read + Debug> Debug for Stream<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Stream({:?})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read> Responder for Stream<T> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
let mut stream = match res.start() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use response::{Responder, Outcome};
|
||||
use http::hyper::{StatusCode, FreshHyperResponse};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StatusResponse<R: Responder> {
|
||||
status: StatusCode,
|
||||
responder: R,
|
||||
|
|
Loading…
Reference in New Issue