use std::fmt;
use std::mem;
use std::io::{self, Read};
use std::marker::PhantomData;
use libflate::non_blocking::gzip;
use tokio_io::AsyncRead;
use tokio_io::io as async_io;
use futures::{Async, Future, Poll, Stream};
use futures::stream::Concat2;
use hyper::StatusCode;
use serde::de::DeserializeOwned;
use serde_json;
use url::Url;
use header::{Headers, ContentEncoding, ContentLength, Encoding, TransferEncoding};
use super::{decoder, body, Body, Chunk, Decoder};
use error;
pub struct Response {
status: StatusCode,
headers: Headers,
url: Url,
body: Decoder,
}
impl Response {
#[inline]
pub fn url(&self) -> &Url {
&self.url
}
#[inline]
pub fn status(&self) -> StatusCode {
self.status
}
#[inline]
pub fn headers(&self) -> &Headers {
&self.headers
}
#[inline]
pub fn headers_mut(&mut self) -> &mut Headers {
&mut self.headers
}
pub fn into_body(self) -> Decoder {
self.body
}
#[inline]
pub fn body(&self) -> &Decoder {
&self.body
}
#[inline]
pub fn body_mut(&mut self) -> &mut Decoder {
&mut self.body
}
#[inline]
pub fn json<T: DeserializeOwned>(&mut self) -> Json<T> {
let body = mem::replace(&mut self.body, Decoder::empty());
Json {
concat: body.concat2(),
_marker: PhantomData,
}
}
#[inline]
pub fn error_for_status(self) -> ::Result<Self> {
if self.status.is_client_error() {
Err(::error::client_error(self.url, self.status))
} else if self.status.is_server_error() {
Err(::error::server_error(self.url, self.status))
} else {
Ok(self)
}
}
}
impl fmt::Debug for Response {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Response")
.field("url", self.url())
.field("status", &self.status())
.field("headers", self.headers())
.finish()
}
}
pub struct Json<T> {
concat: Concat2<Decoder>,
_marker: PhantomData<T>,
}
impl<T: DeserializeOwned> Future for Json<T> {
type Item = T;
type Error = ::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let bytes = try_ready!(self.concat.poll());
let t = try_!(serde_json::from_slice(&bytes));
Ok(Async::Ready(t))
}
}
impl<T> fmt::Debug for Json<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Json")
.finish()
}
}
pub fn new(mut res: ::hyper::client::Response, url: Url, gzip: bool) -> Response {
let status = res.status();
let mut headers = mem::replace(res.headers_mut(), Headers::new());
let decoder = decoder::detect(&mut headers, body::wrap(res.body()), gzip);
debug!("Response: '{}' for {}", status, url);
Response {
status: status,
headers: headers,
url: url,
body: decoder,
}
}