Rename `data` to `content` in `response`. Remove `DataOutcome`.

This commit is contained in:
Sergio Benitez 2016-10-25 13:03:50 +02:00
parent 0a4a647829
commit f5a5ea3a22
17 changed files with 127 additions and 122 deletions

View File

@ -4,9 +4,9 @@ extern crate serde_json;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::io::Read; use std::io::Read;
use rocket::Outcome::*; use rocket::outcome::{Outcome, IntoOutcome};
use rocket::request::{Request, Data, FromData, DataOutcome}; use rocket::request::{data, Request, Data, FromData};
use rocket::response::{self, Responder, data}; use rocket::response::{self, Responder, content};
use rocket::http::StatusCode; use rocket::http::StatusCode;
use rocket::http::hyper::FreshHyperResponse; use rocket::http::hyper::FreshHyperResponse;
@ -71,24 +71,24 @@ const MAX_SIZE: u64 = 1048576;
impl<T: Deserialize> FromData for JSON<T> { impl<T: Deserialize> FromData for JSON<T> {
type Error = SerdeError; type Error = SerdeError;
fn from_data(request: &Request, data: Data) -> DataOutcome<Self, SerdeError> { fn from_data(request: &Request, data: Data) -> data::Outcome<Self, SerdeError> {
if !request.content_type().is_json() { if !request.content_type().is_json() {
error_!("Content-Type is not JSON."); error_!("Content-Type is not JSON.");
return DataOutcome::forward(data); return Outcome::Forward(data);
} }
let reader = data.open().take(MAX_SIZE); let reader = data.open().take(MAX_SIZE);
DataOutcome::of(serde_json::from_reader(reader).map(|val| JSON(val))) serde_json::from_reader(reader).map(|val| JSON(val)).into_outcome()
} }
} }
impl<T: Serialize> Responder for JSON<T> { impl<T: Serialize> Responder for JSON<T> {
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> response::Outcome<'a> { fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> response::Outcome<'a> {
match serde_json::to_string(&self.0) { match serde_json::to_string(&self.0) {
Ok(json_string) => data::JSON(json_string).respond(res), Ok(json_string) => content::JSON(json_string).respond(res),
Err(e) => { Err(e) => {
error_!("JSON failed to serialize: {:?}", e); error_!("JSON failed to serialize: {:?}", e);
Forward((StatusCode::BadRequest, res)) Outcome::Forward((StatusCode::BadRequest, res))
} }
} }
} }

View File

@ -17,10 +17,10 @@ use std::path::{Path, PathBuf};
use std::collections::HashMap; use std::collections::HashMap;
use rocket::config; use rocket::config;
use rocket::response::{Content, Outcome, Responder}; use rocket::response::{self, Content, Responder};
use rocket::http::hyper::FreshHyperResponse; use rocket::http::hyper::FreshHyperResponse;
use rocket::http::{ContentType, StatusCode}; use rocket::http::{ContentType, StatusCode};
use rocket::Outcome::*; use rocket::Outcome;
/// The Template type implements generic support for template rendering in /// The Template type implements generic support for template rendering in
/// Rocket. /// Rocket.
@ -160,7 +160,7 @@ impl Template {
} }
impl Responder for Template { impl Responder for Template {
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> { fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> response::Outcome<'a> {
let content_type = match self.1 { let content_type = match self.1 {
Some(ref ext) => ContentType::from_extension(ext), Some(ref ext) => ContentType::from_extension(ext),
None => ContentType::html() None => ContentType::html()
@ -168,7 +168,7 @@ impl Responder for Template {
match self.0 { match self.0 {
Some(ref render) => Content(content_type, render.as_str()).respond(res), Some(ref render) => Content(content_type, render.as_str()).respond(res),
None => Forward((StatusCode::InternalServerError, res)), None => Outcome::Forward((StatusCode::InternalServerError, res)),
} }
} }
} }

View File

@ -7,7 +7,7 @@ extern crate serde_json;
use rocket::{Request, Error}; use rocket::{Request, Error};
use rocket::http::ContentType; use rocket::http::ContentType;
use rocket::response::data; use rocket::response::content::JSON;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct Person { struct Person {
@ -15,15 +15,17 @@ struct Person {
age: i8, age: i8,
} }
// This shows how to manually serialize some JSON, but in a real application,
// we'd use the JSON contrib type.
#[get("/<name>/<age>", format = "application/json")] #[get("/<name>/<age>", format = "application/json")]
fn hello(content_type: ContentType, name: String, age: i8) -> data::JSON<String> { fn hello(content_type: ContentType, name: String, age: i8) -> JSON<String> {
let person = Person { let person = Person {
name: name, name: name,
age: age, age: age,
}; };
println!("ContentType: {}", content_type); println!("ContentType: {}", content_type);
data::JSON(serde_json::to_string(&person).unwrap()) JSON(serde_json::to_string(&person).unwrap())
} }
#[error(404)] #[error(404)]

View File

@ -6,7 +6,7 @@ extern crate rocket;
use std::io; use std::io;
use rocket::request::Data; use rocket::request::Data;
use rocket::response::data::Plain; use rocket::response::content::Plain;
#[post("/upload", format = "text/plain", data = "<data>")] #[post("/upload", format = "text/plain", data = "<data>")]
fn upload(data: Data) -> io::Result<Plain<String>> { fn upload(data: Data) -> io::Result<Plain<String>> {

View File

@ -3,7 +3,7 @@
extern crate rocket; extern crate rocket;
use rocket::response::{data, Stream}; use rocket::response::{content, Stream};
use std::io::{self, repeat, Repeat, Read, Take}; use std::io::{self, repeat, Repeat, Read, Take};
use std::fs::File; use std::fs::File;
@ -11,8 +11,8 @@ use std::fs::File;
type LimitedRepeat = Take<Repeat>; type LimitedRepeat = Take<Repeat>;
#[get("/")] #[get("/")]
fn root() -> data::Plain<Stream<LimitedRepeat>> { fn root() -> content::Plain<Stream<LimitedRepeat>> {
data::Plain(Stream::from(repeat('a' as u8).take(25000))) content::Plain(Stream::from(repeat('a' as u8).take(25000)))
} }
#[get("/big_file")] #[get("/big_file")]

View File

@ -74,7 +74,7 @@ macro_rules! default_errors {
$( $(
fn $fn_name<'r>(_: Error, _r: &'r Request) -> Response<'r> { fn $fn_name<'r>(_: Error, _r: &'r Request) -> Response<'r> {
Response::with_raw_status($code, Response::with_raw_status($code,
data::HTML(error_page_template!($code, $name, $description)) content::HTML(error_page_template!($code, $name, $description))
) )
} }
@ -91,7 +91,7 @@ pub mod defaults {
use std::collections::HashMap; use std::collections::HashMap;
use request::Request; use request::Request;
use response::{Response, data}; use response::{Response, content};
use error::Error; use error::Error;
pub fn get() -> HashMap<u16, Catcher> { pub fn get() -> HashMap<u16, Catcher> {

View File

@ -86,7 +86,6 @@ use term_painter::Color;
use term_painter::ToStyle; use term_painter::ToStyle;
use self::Outcome::*; use self::Outcome::*;
use http::hyper::{FreshHyperResponse, StatusCode};
/// An enum representing success (`Success`), failure (`Failure`), or /// An enum representing success (`Success`), failure (`Failure`), or
/// forwarding (`Forward`). /// forwarding (`Forward`).
@ -101,28 +100,11 @@ pub enum Outcome<S, E, F> {
Forward(F), Forward(F),
} }
/// Conversion trait from some type into an Outcome type.
pub trait IntoOutcome<S, E, F> { pub trait IntoOutcome<S, E, F> {
fn into_outcome(self) -> Outcome<S, E, F>; fn into_outcome(self) -> Outcome<S, E, F>;
} }
impl<T, E> IntoOutcome<T, (StatusCode, E), ()> for Result<T, E> {
fn into_outcome(self) -> Outcome<T, (StatusCode, E), ()> {
match self {
Ok(val) => Success(val),
Err(val) => Failure((StatusCode::BadRequest, val))
}
}
}
impl<'a, T, E> IntoOutcome<(), (), (StatusCode, FreshHyperResponse<'a>)> for Result<T, E> {
fn into_outcome(self) -> Outcome<(), (), (StatusCode, FreshHyperResponse<'a>)> {
match self {
Ok(_) => Success(()),
Err(_) => Failure(())
}
}
}
impl<S, E, F> Outcome<S, E, F> { impl<S, E, F> Outcome<S, E, F> {
/// Unwraps the Outcome, yielding the contents of a Success. /// Unwraps the Outcome, yielding the contents of a Success.
/// ///

View File

@ -1,33 +1,18 @@
use outcome::Outcome; use outcome::{self, IntoOutcome};
use outcome::Outcome::*;
use http::StatusCode; use http::StatusCode;
use request::{Request, Data}; use request::{Request, Data};
/// Type alias for the `Outcome` of a `FromData` conversion. /// Type alias for the `Outcome` of a `FromData` conversion.
pub type DataOutcome<S, E> = Outcome<S, (StatusCode, E), Data>; pub type Outcome<S, E> = outcome::Outcome<S, (StatusCode, E), Data>;
impl<S, E> DataOutcome<S, E> { impl<'a, S, E> IntoOutcome<S, (StatusCode, E), Data> for Result<S, E> {
#[inline(always)] fn into_outcome(self) -> Outcome<S, E> {
pub fn of(result: Result<S, E>) -> Self { match self {
match result { Ok(val) => Success(val),
Ok(val) => DataOutcome::success(val), Err(err) => Failure((StatusCode::InternalServerError, err))
Err(err) => DataOutcome::failure(StatusCode::InternalServerError, err)
} }
} }
#[inline(always)]
pub fn success(s: S) -> Self {
Outcome::Success(s)
}
#[inline(always)]
pub fn failure(status: StatusCode, e: E) -> Self {
Outcome::Failure((status, e))
}
#[inline(always)]
pub fn forward(data: Data) -> Self {
Outcome::Forward(data)
}
} }
/// Trait used to derive an object from incoming request data. /// Trait used to derive an object from incoming request data.
@ -75,25 +60,25 @@ pub trait FromData: Sized {
/// If the parse is successful, an outcome of `Success` is returned. If the /// If the parse is successful, an outcome of `Success` is returned. If the
/// data does not correspond to the type of `Self`, `Forward` is returned. /// data does not correspond to the type of `Self`, `Forward` is returned.
/// If parsing fails, `Failure` is returned. /// If parsing fails, `Failure` is returned.
fn from_data(request: &Request, data: Data) -> DataOutcome<Self, Self::Error>; fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error>;
} }
/// The identity implementation of `FromData`. Always returns `Success`. /// The identity implementation of `FromData`. Always returns `Success`.
impl FromData for Data { impl FromData for Data {
type Error = (); type Error = ();
fn from_data(_: &Request, data: Data) -> DataOutcome<Self, Self::Error> { fn from_data(_: &Request, data: Data) -> Outcome<Self, Self::Error> {
DataOutcome::success(data) Success(data)
} }
} }
impl<T: FromData> FromData for Result<T, T::Error> { impl<T: FromData> FromData for Result<T, T::Error> {
type Error = (); type Error = ();
fn from_data(request: &Request, data: Data) -> DataOutcome<Self, Self::Error> { fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> {
match T::from_data(request, data) { match T::from_data(request, data) {
Outcome::Success(val) => DataOutcome::success(Ok(val)), Success(val) => Success(Ok(val)),
Outcome::Failure((_, val)) => DataOutcome::success(Err(val)), Failure((_, val)) => Success(Err(val)),
Outcome::Forward(data) => DataOutcome::forward(data), Forward(data) => Forward(data),
} }
} }
} }
@ -101,11 +86,11 @@ impl<T: FromData> FromData for Result<T, T::Error> {
impl<T: FromData> FromData for Option<T> { impl<T: FromData> FromData for Option<T> {
type Error = (); type Error = ();
fn from_data(request: &Request, data: Data) -> DataOutcome<Self, Self::Error> { fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> {
match T::from_data(request, data) { match T::from_data(request, data) {
Outcome::Success(val) => DataOutcome::success(Some(val)), Success(val) => Success(Some(val)),
Outcome::Failure(_) => DataOutcome::success(None), Failure(_) => Success(None),
Outcome::Forward(_) => DataOutcome::success(None) Forward(_) => Success(None)
} }
} }
} }

View File

@ -5,7 +5,7 @@
#[cfg(not(any(test, feature = "testing")))] pub mod data_stream; #[cfg(not(any(test, feature = "testing")))] pub mod data_stream;
mod from_data; mod from_data;
pub use self::from_data::{FromData, DataOutcome}; pub use self::from_data::{FromData, Outcome};
#[cfg(any(test, feature = "testing"))] pub use self::test_data::Data; #[cfg(any(test, feature = "testing"))] pub use self::test_data::Data;
#[cfg(not(any(test, feature = "testing")))] pub use self::data::Data; #[cfg(not(any(test, feature = "testing")))] pub use self::data::Data;

View File

@ -28,7 +28,8 @@ use std::fmt::{self, Debug};
use std::io::Read; use std::io::Read;
use http::StatusCode; use http::StatusCode;
use request::{Request, FromData, Data, DataOutcome}; use request::{data, Request, FromData, Data};
use outcome::Outcome::*;
// TODO: This works and is safe, but the lifetime appears twice. // TODO: This works and is safe, but the lifetime appears twice.
/// A `FromData` type for parsing `FromForm` types. /// A `FromData` type for parsing `FromForm` types.
@ -230,23 +231,23 @@ impl<'f, T: FromForm<'f> + Debug + 'f> Debug for Form<'f, T> {
impl<'f, T: FromForm<'f>> FromData for Form<'f, T> where T::Error: Debug { impl<'f, T: FromForm<'f>> FromData for Form<'f, T> where T::Error: Debug {
type Error = Option<String>; type Error = Option<String>;
fn from_data(request: &Request, data: Data) -> DataOutcome<Self, Self::Error> { fn from_data(request: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
if !request.content_type().is_form() { if !request.content_type().is_form() {
warn_!("Form data does not have form content type."); warn_!("Form data does not have form content type.");
return DataOutcome::forward(data); return Forward(data);
} }
let mut form_string = String::with_capacity(4096); let mut form_string = String::with_capacity(4096);
let mut stream = data.open().take(32768); let mut stream = data.open().take(32768);
if let Err(e) = stream.read_to_string(&mut form_string) { if let Err(e) = stream.read_to_string(&mut form_string) {
error_!("IO Error: {:?}", e); error_!("IO Error: {:?}", e);
DataOutcome::failure(StatusCode::InternalServerError, None) Failure((StatusCode::InternalServerError, None))
} else { } else {
match Form::new(form_string) { match Form::new(form_string) {
Ok(form) => DataOutcome::success(form), Ok(form) => Success(form),
Err((form_string, e)) => { Err((form_string, e)) => {
error_!("Failed to parse value from form: {:?}", e); error_!("Failed to parse value from form: {:?}", e);
DataOutcome::failure(StatusCode::BadRequest, Some(form_string)) Failure((StatusCode::BadRequest, Some(form_string)))
} }
} }
} }

View File

@ -1,6 +1,6 @@
use std::fmt::Debug; use std::fmt::Debug;
use outcome; use outcome::{self, IntoOutcome};
use request::Request; use request::Request;
use outcome::Outcome::*; use outcome::Outcome::*;
use http::{StatusCode, ContentType, Method, Cookies}; use http::{StatusCode, ContentType, Method, Cookies};
@ -8,6 +8,15 @@ use http::{StatusCode, ContentType, Method, Cookies};
/// Type alias for the `Outcome` of a `FromRequest` conversion. /// Type alias for the `Outcome` of a `FromRequest` conversion.
pub type Outcome<T, E> = outcome::Outcome<T, (StatusCode, E), ()>; pub type Outcome<T, E> = outcome::Outcome<T, (StatusCode, E), ()>;
impl<T, E> IntoOutcome<T, (StatusCode, E), ()> for Result<T, E> {
fn into_outcome(self) -> Outcome<T, E> {
match self {
Ok(val) => Success(val),
Err(val) => Failure((StatusCode::BadRequest, val))
}
}
}
pub trait FromRequest<'r>: Sized { pub trait FromRequest<'r>: Sized {
type Error: Debug; type Error: Debug;

View File

@ -17,11 +17,12 @@
mod request; mod request;
mod param; mod param;
mod form; mod form;
mod data;
mod from_request; mod from_request;
pub mod data;
pub use self::request::Request; pub use self::request::Request;
pub use self::from_request::{FromRequest, Outcome}; pub use self::from_request::{FromRequest, Outcome};
pub use self::param::{FromParam, FromSegments}; pub use self::param::{FromParam, FromSegments};
pub use self::form::{Form, FromForm, FromFormValue, FormItems}; pub use self::form::{Form, FromForm, FromFormValue, FormItems};
pub use self::data::{Data, FromData, DataOutcome}; pub use self::data::{Data, FromData};

View File

@ -0,0 +1,12 @@
use outcome::Outcome;
use response::{self, Responder};
use http::hyper::{FreshHyperResponse, StatusCode};
#[derive(Debug)]
pub struct Failure(pub StatusCode);
impl Responder for Failure {
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> response::Outcome<'a> {
Outcome::Forward((self.0, res))
}
}

View File

@ -4,49 +4,17 @@ mod with_status;
mod flash; mod flash;
mod named_file; mod named_file;
mod stream; mod stream;
mod response;
mod failure;
pub mod data; pub mod content;
pub use self::response::Response;
pub use self::responder::{Outcome, Responder}; pub use self::responder::{Outcome, Responder};
pub use self::redirect::Redirect; pub use self::redirect::Redirect;
pub use self::with_status::StatusResponse; pub use self::with_status::StatusResponse;
pub use self::flash::Flash; pub use self::flash::Flash;
pub use self::named_file::NamedFile; pub use self::named_file::NamedFile;
pub use self::stream::Stream; pub use self::stream::Stream;
pub use self::data::Content; pub use self::content::Content;
pub use self::failure::Failure;
use outcome;
use request::Data;
use http::hyper::StatusCode;
use outcome::Outcome::*;
pub type Response<'a> = outcome::Outcome<Box<Responder + 'a>, StatusCode, Data>;
impl<'a> Response<'a> {
#[inline(always)]
pub fn success<T: Responder + 'a>(responder: T) -> Response<'a> {
Success(Box::new(responder))
}
#[inline(always)]
pub fn failure(code: StatusCode) -> Response<'static> {
Failure(code)
}
#[inline(always)]
pub fn forward(data: Data) -> Response<'static> {
Forward(data)
}
#[inline(always)]
pub fn with_raw_status<T: Responder + 'a>(status: u16, body: T) -> Response<'a> {
let status_code = StatusCode::from_u16(status);
Response::success(StatusResponse::new(status_code, body))
}
#[doc(hidden)]
#[inline(always)]
pub fn responder(self) -> Option<Box<Responder + 'a>> {
self.succeeded()
}
}

View File

@ -9,6 +9,16 @@ use outcome::Outcome::*;
pub type Outcome<'a> = outcome::Outcome<(), (), (StatusCode, FreshHyperResponse<'a>)>; pub type Outcome<'a> = outcome::Outcome<(), (), (StatusCode, FreshHyperResponse<'a>)>;
impl<'a, T, E> IntoOutcome<(), (), (StatusCode, FreshHyperResponse<'a>)> for Result<T, E> {
fn into_outcome(self) -> Outcome<'a> {
match self {
Ok(_) => Success(()),
Err(_) => Failure(())
}
}
}
pub trait Responder { pub trait Responder {
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a>; fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a>;
} }

View File

@ -0,0 +1,35 @@
use request::Data;
use outcome::{self, Outcome};
use http::hyper::StatusCode;
use response::{Responder, StatusResponse};
pub type Response<'a> = outcome::Outcome<Box<Responder + 'a>, StatusCode, Data>;
impl<'a> Response<'a> {
#[inline(always)]
pub fn success<T: Responder + 'a>(responder: T) -> Response<'a> {
Outcome::Success(Box::new(responder))
}
#[inline(always)]
pub fn failure(code: StatusCode) -> Response<'static> {
Outcome::Failure(code)
}
#[inline(always)]
pub fn forward(data: Data) -> Response<'static> {
Outcome::Forward(data)
}
#[inline(always)]
pub fn with_raw_status<T: Responder + 'a>(status: u16, body: T) -> Response<'a> {
let status_code = StatusCode::from_u16(status);
Response::success(StatusResponse::new(status_code, body))
}
#[doc(hidden)]
#[inline(always)]
pub fn responder(self) -> Option<Box<Responder + 'a>> {
self.succeeded()
}
}