mirror of https://github.com/rwf2/Rocket.git
Make Outcome generic on its encapsulated type.
This commit is contained in:
parent
d321e1de8d
commit
be3530bb44
|
@ -4,7 +4,7 @@ extern crate serde_json;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use rocket::request::{Request, FromRequest};
|
||||
use rocket::response::{Responder, Outcome, data};
|
||||
use rocket::response::{Responder, Outcome, ResponseOutcome, data};
|
||||
use rocket::http::hyper::FreshHyperResponse;
|
||||
|
||||
use self::serde::{Serialize, Deserialize};
|
||||
|
@ -70,7 +70,7 @@ impl<'r, 'c, T: Deserialize> FromRequest<'r, 'c> for JSON<T> {
|
|||
}
|
||||
|
||||
impl<T: Serialize> Responder for JSON<T> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
match serde_json::to_string(&self.0) {
|
||||
Ok(json_string) => data::JSON(json_string).respond(res),
|
||||
Err(e) => {
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::collections::HashMap;
|
||||
|
||||
use rocket::Rocket;
|
||||
use rocket::response::{Content, Outcome, Responder};
|
||||
use rocket::response::{Content, Outcome, ResponseOutcome, Responder};
|
||||
use rocket::http::hyper::FreshHyperResponse;
|
||||
use rocket::http::ContentType;
|
||||
|
||||
|
@ -133,7 +133,7 @@ impl Template {
|
|||
}
|
||||
|
||||
impl Responder for Template {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
let content_type = match self.1 {
|
||||
Some(ref ext) => ContentType::from_extension(ext),
|
||||
None => ContentType::html()
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
use std::io::Read;
|
||||
|
||||
pub struct Data {
|
||||
stream: Box<Read>
|
||||
}
|
||||
|
||||
pub trait FromData {
|
||||
fn from_data(data: Data) -> Outcome { }
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use response::{Responder, Outcome};
|
||||
use response::{Responder, ResponseOutcome};
|
||||
use http::hyper::{header, FreshHyperResponse};
|
||||
use http::mime::{Mime, TopLevel, SubLevel};
|
||||
use http::ContentType;
|
||||
|
@ -6,7 +6,7 @@ use http::ContentType;
|
|||
pub struct Content<T: Responder>(pub ContentType, pub T);
|
||||
|
||||
impl<T: Responder> Responder for Content<T> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> ResponseOutcome<'b> {
|
||||
res.headers_mut().set(header::ContentType(self.0.clone().into()));
|
||||
self.1.respond(res)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ macro_rules! impl_data_type_responder {
|
|||
pub struct $name<T: Responder>(pub T);
|
||||
|
||||
impl<T: Responder> Responder for $name<T> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> ResponseOutcome<'b> {
|
||||
let mime = Mime(TopLevel::$top, SubLevel::$sub, vec![]);
|
||||
res.headers_mut().set(header::ContentType(mime));
|
||||
self.0.respond(res)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::io::Write;
|
||||
|
||||
use response::{Outcome, Responder};
|
||||
use response::{ResponseOutcome, Outcome, Responder};
|
||||
use http::hyper::{header, FreshHyperResponse};
|
||||
use http::hyper::StatusCode;
|
||||
|
||||
|
@ -13,20 +13,20 @@ impl Empty {
|
|||
}
|
||||
|
||||
impl Responder for Empty {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
res.headers_mut().set(header::ContentLength(0));
|
||||
*(res.status_mut()) = self.0;
|
||||
|
||||
let mut stream = res.start().unwrap();
|
||||
stream.write_all(b"").unwrap();
|
||||
Outcome::Complete
|
||||
Outcome::Success
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Forward;
|
||||
|
||||
impl Responder for Forward {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
Outcome::FailForward(res)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::convert::AsRef;
|
||||
|
||||
use response::{Outcome, Responder};
|
||||
use response::{ResponseOutcome, Responder};
|
||||
use request::{Request, FromRequest};
|
||||
use http::hyper::{HyperSetCookie, HyperCookiePair, FreshHyperResponse};
|
||||
|
||||
|
@ -43,7 +43,7 @@ impl<R: Responder> Flash<R> {
|
|||
}
|
||||
|
||||
impl<R: Responder> Responder for Flash<R> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> ResponseOutcome<'b> {
|
||||
trace_!("Flash: setting message: {}:{}", self.name, self.message);
|
||||
res.headers_mut().set(HyperSetCookie(vec![self.cookie_pair()]));
|
||||
self.responder.respond(res)
|
||||
|
|
|
@ -13,7 +13,7 @@ pub use self::responder::Responder;
|
|||
pub use self::empty::{Empty, Forward};
|
||||
pub use self::redirect::Redirect;
|
||||
pub use self::with_status::StatusResponse;
|
||||
pub use self::outcome::Outcome;
|
||||
pub use self::outcome::{Outcome, ResponseOutcome};
|
||||
pub use self::flash::Flash;
|
||||
pub use self::named_file::NamedFile;
|
||||
pub use self::stream::Stream;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::io;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use response::{Responder, Outcome};
|
||||
use response::{Responder, ResponseOutcome};
|
||||
use http::hyper::{header, FreshHyperResponse};
|
||||
use http::ContentType;
|
||||
|
||||
|
@ -33,7 +33,7 @@ impl NamedFile {
|
|||
}
|
||||
|
||||
impl Responder for NamedFile {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
if let Some(ext) = self.path().extension() {
|
||||
let ext_string = ext.to_string_lossy().to_lowercase();
|
||||
let content_type = ContentType::from_extension(&ext_string);
|
||||
|
|
|
@ -5,21 +5,26 @@ use term_painter::ToStyle;
|
|||
|
||||
use http::hyper::FreshHyperResponse;
|
||||
|
||||
pub enum Outcome<'h> {
|
||||
pub enum Outcome<T> {
|
||||
/// Signifies a response that completed sucessfully.
|
||||
Complete,
|
||||
/// Signifies a response that failed internally.
|
||||
Bad(FreshHyperResponse<'h>),
|
||||
/// Signifies a failing response where no further processing should happen.
|
||||
Success,
|
||||
/// Signifies a failing response that started responding but fail, so no
|
||||
/// further processing can occur.
|
||||
FailStop,
|
||||
/// Signifies a failing response whose request should be processed further.
|
||||
FailForward(FreshHyperResponse<'h>),
|
||||
/// Signifies a response that failed internally without beginning to
|
||||
/// respond but no further processing should occur.
|
||||
Bad(T),
|
||||
/// Signifies a failing response that failed internally without beginning to
|
||||
/// respond. Further processing should be attempted.
|
||||
FailForward(T),
|
||||
}
|
||||
|
||||
impl<'h> Outcome<'h> {
|
||||
pub type ResponseOutcome<'a> = Outcome<FreshHyperResponse<'a>>;
|
||||
|
||||
impl<T> Outcome<T> {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match *self {
|
||||
Outcome::Complete => "Complete",
|
||||
Outcome::Success => "Success",
|
||||
Outcome::FailStop => "FailStop",
|
||||
Outcome::Bad(..) => "Bad",
|
||||
Outcome::FailForward(..) => "FailForward",
|
||||
|
@ -28,7 +33,7 @@ impl<'h> Outcome<'h> {
|
|||
|
||||
fn as_int(&self) -> isize {
|
||||
match *self {
|
||||
Outcome::Complete => 0,
|
||||
Outcome::Success => 0,
|
||||
Outcome::Bad(..) => 1,
|
||||
Outcome::FailStop => 2,
|
||||
Outcome::FailForward(..) => 3,
|
||||
|
@ -36,22 +41,22 @@ impl<'h> Outcome<'h> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'h> PartialEq for Outcome<'h> {
|
||||
fn eq(&self, other: &Outcome<'h>) -> bool {
|
||||
impl<T> PartialEq for Outcome<T> {
|
||||
fn eq(&self, other: &Outcome<T>) -> bool {
|
||||
self.as_int() == other.as_int()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'h> fmt::Debug for Outcome<'h> {
|
||||
impl<T> fmt::Debug for Outcome<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Outcome::{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'h> fmt::Display for Outcome<'h> {
|
||||
impl<T> fmt::Display for Outcome<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Outcome::Complete => write!(f, "{}", Green.paint("Complete")),
|
||||
Outcome::Success => write!(f, "{}", Green.paint("Success")),
|
||||
Outcome::Bad(..) => write!(f, "{}", Yellow.paint("Bad Completion")),
|
||||
Outcome::FailStop => write!(f, "{}", Red.paint("Failed")),
|
||||
Outcome::FailForward(..) => write!(f, "{}", Cyan.paint("Forwarding")),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use response::{Outcome, Responder};
|
||||
use response::{ResponseOutcome, Outcome, Responder};
|
||||
use http::hyper::{header, FreshHyperResponse, StatusCode};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -27,11 +27,11 @@ impl Redirect {
|
|||
}
|
||||
|
||||
impl<'a> Responder for Redirect {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> ResponseOutcome<'b> {
|
||||
res.headers_mut().set(header::ContentLength(0));
|
||||
res.headers_mut().set(header::Location(self.1.clone()));
|
||||
*(res.status_mut()) = self.0;
|
||||
res.send(b"").unwrap();
|
||||
Outcome::Complete
|
||||
Outcome::Success
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::io::{Read, Write};
|
|||
use std::fs::File;
|
||||
use std::fmt;
|
||||
|
||||
use response::Outcome;
|
||||
use response::{Outcome, ResponseOutcome};
|
||||
use http::mime::{Mime, TopLevel, SubLevel};
|
||||
use http::hyper::{header, FreshHyperResponse, StatusCode};
|
||||
|
||||
|
@ -11,29 +11,29 @@ use http::hyper::{header, FreshHyperResponse, StatusCode};
|
|||
// In particular, we want to try the next ranked route when when parsing
|
||||
// parameters doesn't work out.
|
||||
pub trait Responder {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a>;
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> ResponseOutcome<'a>;
|
||||
}
|
||||
|
||||
impl<'a> Responder for &'a str {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> ResponseOutcome<'b> {
|
||||
if res.headers().get::<header::ContentType>().is_none() {
|
||||
let mime = Mime(TopLevel::Text, SubLevel::Plain, vec![]);
|
||||
res.headers_mut().set(header::ContentType(mime));
|
||||
}
|
||||
|
||||
res.send(self.as_bytes()).unwrap();
|
||||
Outcome::Complete
|
||||
Outcome::Success
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for String {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
if res.headers().get::<header::ContentType>().is_none() {
|
||||
let mime = Mime(TopLevel::Text, SubLevel::Html, vec![]);
|
||||
res.headers_mut().set(header::ContentType(mime));
|
||||
}
|
||||
res.send(self.as_bytes()).unwrap();
|
||||
Outcome::Complete
|
||||
Outcome::Success
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ impl Responder for String {
|
|||
// a way to retrieve a file based on its fd, strangely enough. See...
|
||||
// https://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c
|
||||
impl Responder for File {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
let size = self.metadata().unwrap().len();
|
||||
|
||||
res.headers_mut().set(header::ContentLength(size));
|
||||
|
@ -53,12 +53,12 @@ impl Responder for File {
|
|||
|
||||
let mut stream = res.start().unwrap();
|
||||
stream.write_all(&v).unwrap();
|
||||
Outcome::Complete
|
||||
Outcome::Success
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Responder> Responder for Option<T> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
if self.is_none() {
|
||||
trace!("Option is none.");
|
||||
// TODO: Should this be a 404 or 500?
|
||||
|
@ -71,7 +71,7 @@ impl<T: Responder> Responder for Option<T> {
|
|||
|
||||
impl<T: Responder, E: fmt::Debug> Responder for Result<T, E> {
|
||||
// prepend with `default` when using impl specialization
|
||||
default fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
default fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
if self.is_err() {
|
||||
error_!("{:?}", self.as_ref().err().unwrap());
|
||||
// TODO: Should this be a 404 or 500?
|
||||
|
@ -83,7 +83,7 @@ impl<T: Responder, E: fmt::Debug> Responder for Result<T, E> {
|
|||
}
|
||||
|
||||
impl<T: Responder, E: Responder + fmt::Debug> Responder for Result<T, E> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
match *self {
|
||||
Ok(ref mut responder) => responder.respond(res),
|
||||
Err(ref mut responder) => responder.respond(res),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::io::{Read, Write, ErrorKind};
|
||||
|
||||
use response::{Responder, Outcome};
|
||||
use response::{Responder, Outcome, ResponseOutcome};
|
||||
use http::hyper::FreshHyperResponse;
|
||||
|
||||
// TODO: Support custom chunk sizes.
|
||||
|
@ -26,7 +26,7 @@ impl<T: Read> Stream<T> {
|
|||
}
|
||||
|
||||
impl<T: Read> Responder for Stream<T> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> ResponseOutcome<'a> {
|
||||
let mut stream = res.start().unwrap();
|
||||
let mut buffer = [0; CHUNK_SIZE];
|
||||
let mut complete = false;
|
||||
|
@ -55,6 +55,6 @@ impl<T: Read> Responder for Stream<T> {
|
|||
return Outcome::FailStop;
|
||||
}
|
||||
|
||||
Outcome::Complete
|
||||
Outcome::Success
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use response::{Responder, Outcome};
|
||||
use response::{Responder, ResponseOutcome};
|
||||
use http::hyper::{StatusCode, FreshHyperResponse};
|
||||
|
||||
pub struct StatusResponse<R: Responder> {
|
||||
|
@ -16,7 +16,7 @@ impl<R: Responder> StatusResponse<R> {
|
|||
}
|
||||
|
||||
impl<R: Responder> Responder for StatusResponse<R> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> Outcome<'b> {
|
||||
fn respond<'b>(&mut self, mut res: FreshHyperResponse<'b>) -> ResponseOutcome<'b> {
|
||||
*(res.status_mut()) = self.status;
|
||||
self.responder.respond(res)
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ impl Rocket {
|
|||
|
||||
// Get the result if we failed forward so we can try again.
|
||||
res = match outcome {
|
||||
Outcome::Complete | Outcome::FailStop => return,
|
||||
Outcome::Success | Outcome::FailStop => return,
|
||||
Outcome::FailForward(r) => r,
|
||||
Outcome::Bad(r) => return self.handle_internal_error(&request, r),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue