Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Response more generic #1164

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions benches/end_to_end.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn get_one_at_a_time(b: &mut test::Bencher) {
b.bytes = 160 * 2 + PHRASE.len() as u64;
b.iter(move || {
let work = client.get(url.clone()).and_then(|res| {
res.body().for_each(|_chunk| {
res.into_body().unwrap_or_default().for_each(|_chunk| {
Ok(())
})
});
Expand Down Expand Up @@ -61,7 +61,7 @@ fn post_one_at_a_time(b: &mut test::Bencher) {
req.set_body(post);

let work = client.request(req).and_then(|res| {
res.body().for_each(|_chunk| {
res.into_body().unwrap_or_default().for_each(|_chunk| {
Ok(())
})
});
Expand All @@ -85,7 +85,7 @@ impl Service for Hello {
server::Response::new()
.with_header(ContentLength(PHRASE.len() as u64))
.with_header(ContentType::plaintext())
.with_body(PHRASE)
.with_body(Some(PHRASE.into()))
)
}

Expand Down
2 changes: 1 addition & 1 deletion examples/client.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn main() {
println!("Response: {}", res.status());
println!("Headers: \n{}", res.headers());

res.body().for_each(|chunk| {
res.into_body().unwrap_or_default().for_each(|chunk| {
io::stdout().write_all(&chunk).map_err(From::from)
})
}).map(|_| {
Expand Down
2 changes: 1 addition & 1 deletion examples/hello.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl Service for Hello {
Response::new()
.with_header(ContentLength(PHRASE.len() as u64))
.with_header(ContentType::plaintext())
.with_body(PHRASE)
.with_body(Some(PHRASE.into()))
)
}

Expand Down
4 changes: 2 additions & 2 deletions examples/server.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ impl Service for Echo {
(&Get, "/") | (&Get, "/echo") => {
Response::new()
.with_header(ContentLength(INDEX.len() as u64))
.with_body(INDEX)
.with_body(Some(INDEX.into()))
},
(&Post, "/echo") => {
let mut res = Response::new();
if let Some(len) = req.headers().get::<ContentLength>() {
res.headers_mut().set(len.clone());
}
res.with_body(req.body())
res.with_body(Some(req.body()))
},
_ => {
Response::new()
Expand Down
1 change: 1 addition & 0 deletions src/http/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use version::HttpVersion;
use std::net::SocketAddr;

/// A client request to a remote server.
#[derive(Clone)]
pub struct Request<B = Body> {
method: Method,
uri: Uri,
Expand Down
85 changes: 66 additions & 19 deletions src/http/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,29 @@ use status::StatusCode;
use version::HttpVersion;

/// A response for a client request to a remote server.
pub struct Response<B = Body> {
#[derive(Clone)]
pub struct Response<B = Option<Body>> {
version: HttpVersion,
headers: Headers,
status: StatusCode,
raw_status: RawStatus,
body: Option<B>,
body: B,
}

impl<B> Response<B> {
impl Response {
/// Constructs a default response
#[inline]
pub fn new() -> Response<B> {
pub fn new() -> Response {
Response::default()
}
}

impl<B> Response<B> {
/// Constructs a default response with a given body
#[inline]
pub fn new_with_body(body: B) -> Response<B> {
Response::<()>::default().with_body(body)
}

/// Get the HTTP version of this response.
#[inline]
Expand Down Expand Up @@ -80,40 +89,77 @@ impl<B> Response<B> {
/// Set the body.
#[inline]
pub fn set_body<T: Into<B>>(&mut self, body: T) {
self.body = Some(body.into());
self.body = body.into();
}

/// Set the body and move the Response.
///
/// Useful for the "builder-style" pattern.
#[inline]
pub fn with_body<T: Into<B>>(mut self, body: T) -> Self {
self.set_body(body);
self
pub fn with_body<B_>(self, body: B_) -> Response<B_> {
let Response {
version: version_,
headers: headers_,
status: status_,
raw_status: raw_status_,
..
} = self;

Response {
version: version_,
headers: headers_,
status: status_,
raw_status: raw_status_,
body: body,
}
}

/// Get a reference to the body.
pub fn body(&self) -> &B { &self.body }

/// Get a mutable reference to the body.
pub fn body_mut(&mut self) -> &mut B { &mut self.body }

/// Take the body, moving it out of the Response.
#[inline]
pub fn take_body(self) -> (B, Response<()>) {
let Response {
version: version_,
headers: headers_,
status: status_,
raw_status: raw_status_,
body: body_,
} = self;

(body_, Response {
version: version_,
headers: headers_,
status: status_,
raw_status: raw_status_,
body: (),
})
}
}

impl Response<Body> {
/// Take the `Body` of this response.
/// Take the body of this response.
#[inline]
pub fn body(self) -> Body {
self.body.unwrap_or_default()
pub fn into_body(self) -> B {
self.body
}
}

impl<B> Default for Response<B> {
impl<B: Default> Default for Response<B> {
fn default() -> Response<B> {
Response::<B> {
version: Default::default(),
headers: Default::default(),
status: Default::default(),
raw_status: Default::default(),
body: None,
body: Default::default(),
}
}
}

impl fmt::Debug for Response {
impl<B> fmt::Debug for Response<B> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Response")
.field("status", &self.status)
Expand All @@ -125,13 +171,14 @@ impl fmt::Debug for Response {

/// Constructs a response using a received ResponseHead and optional body
#[inline]
pub fn from_wire<B>(incoming: ResponseHead, body: Option<B>) -> Response<B> {
pub fn from_wire<B: Default>(incoming: ResponseHead, body: Option<B>)
-> Response<Option<B>> {
let status = incoming.status();
trace!("Response::new");
debug!("version={:?}, status={:?}", incoming.version, status);
debug!("headers={:?}", incoming.headers);

Response::<B> {
Response {
status: status,
version: incoming.version,
headers: incoming.headers,
Expand All @@ -142,7 +189,7 @@ pub fn from_wire<B>(incoming: ResponseHead, body: Option<B>) -> Response<B> {

/// Splits this response into a MessageHead<StatusCode> and its body
#[inline]
pub fn split<B>(res: Response<B>) -> (MessageHead<StatusCode>, Option<B>) {
pub fn split<B>(res: Response<B>) -> (MessageHead<StatusCode>, B) {
let head = MessageHead::<StatusCode> {
version: res.version,
headers: res.headers,
Expand Down
Empty file modified src/lib.rs
100644 → 100755
Empty file.
18 changes: 9 additions & 9 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
/// The returned `Server` contains one method, `run`, which is used to
/// actually run the server.
pub fn bind<S, Bd>(&self, addr: &SocketAddr, new_service: S) -> ::Result<Server<S, Bd>>
where S: NewService<Request = Request, Response = Response<Bd>, Error = ::Error> +
where S: NewService<Request = Request, Response = Response<Option<Bd>>, Error = ::Error> +
Send + Sync + 'static,
Bd: Stream<Item=B, Error=::Error>,
{
Expand Down Expand Up @@ -122,7 +122,7 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
io: I,
remote_addr: SocketAddr,
service: S)
where S: Service<Request = Request, Response = Response<Bd>, Error = ::Error> + 'static,
where S: Service<Request = Request, Response = Response<Option<Bd>>, Error = ::Error> + 'static,
Bd: Stream<Item=B, Error=::Error> + 'static,
I: AsyncRead + AsyncWrite + 'static,
{
Expand Down Expand Up @@ -287,11 +287,11 @@ impl From<Message<__ProtoRequest, http::TokioBody>> for Request {
}
}

impl<B> Into<Message<__ProtoResponse, B>> for Response<B> {
fn into(self) -> Message<__ProtoResponse, B> {
impl<B_, B: Into<Option<B_>>> Into<Message<__ProtoResponse, B_>> for Response<B> {
fn into(self) -> Message<__ProtoResponse, B_> {
let (head, body) = response::split(self);
if let Some(body) = body {
Message::WithBody(__ProtoResponse(head), body.into())
if let Some(body) = body.into() {
Message::WithBody(__ProtoResponse(head), body)
} else {
Message::WithoutBody(__ProtoResponse(head))
}
Expand All @@ -306,14 +306,14 @@ struct HttpService<T> {
type ResponseHead = http::MessageHead<::StatusCode>;

impl<T, B> Service for HttpService<T>
where T: Service<Request=Request, Response=Response<B>, Error=::Error>,
where T: Service<Request=Request, Response=Response<Option<B>>, Error=::Error>,
B: Stream<Error=::Error>,
B::Item: AsRef<[u8]>,
{
type Request = Message<__ProtoRequest, http::TokioBody>;
type Response = Message<__ProtoResponse, B>;
type Error = ::Error;
type Future = Map<T::Future, fn(Response<B>) -> Message<__ProtoResponse, B>>;
type Future = Map<T::Future, fn(Response<Option<B>>) -> Message<__ProtoResponse, B>>;

fn call(&self, message: Self::Request) -> Self::Future {
let (head, body) = match message {
Expand All @@ -326,7 +326,7 @@ impl<T, B> Service for HttpService<T>
}

impl<S, B> Server<S, B>
where S: NewService<Request = Request, Response = Response<B>, Error = ::Error>
where S: NewService<Request = Request, Response = Response<Option<B>>, Error = ::Error>
+ Send + Sync + 'static,
B: Stream<Error=::Error> + 'static,
B::Item: AsRef<[u8]>,
Expand Down
2 changes: 1 addition & 1 deletion tests/server.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl Service for TestService {
*res.headers_mut() = headers;
},
Reply::Body(body) => {
res.set_body(body);
res.set_body(Some(body.into()));
},
}
}
Expand Down