Add Response::text() to async Client
This commit is contained in:
		| @@ -2,13 +2,16 @@ use std::fmt; | ||||
| use std::mem; | ||||
| use std::marker::PhantomData; | ||||
| use std::net::SocketAddr; | ||||
| use std::borrow::Cow; | ||||
|  | ||||
| use encoding_rs::{Encoding, UTF_8}; | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures::stream::Concat2; | ||||
| use http; | ||||
| use hyper::{HeaderMap, StatusCode, Version}; | ||||
| use hyper::client::connect::HttpInfo; | ||||
| use hyper::header::{CONTENT_LENGTH}; | ||||
| use mime::Mime; | ||||
| use tokio::timer::Delay; | ||||
| use serde::de::DeserializeOwned; | ||||
| use serde_json; | ||||
| @@ -135,6 +138,35 @@ impl Response { | ||||
|         self.version | ||||
|     } | ||||
|  | ||||
|     /// Get the response text | ||||
|     pub fn text(&mut self) -> impl Future<Item = String, Error = ::Error> { | ||||
|         self.text_with_charset("utf-8") | ||||
|     } | ||||
|  | ||||
|     /// Get the response text given a specific encoding | ||||
|     pub fn text_with_charset(&mut self, default_encoding: &str) -> impl Future<Item = String, Error = ::Error> { | ||||
|         let body = mem::replace(&mut self.body, Decoder::empty()); | ||||
|         let content_type = self.headers.get(::header::CONTENT_TYPE) | ||||
|             .and_then(|value| { | ||||
|                 value.to_str().ok() | ||||
|             }) | ||||
|             .and_then(|value| { | ||||
|                 value.parse::<Mime>().ok() | ||||
|             }); | ||||
|         let encoding_name = content_type | ||||
|             .as_ref() | ||||
|             .and_then(|mime| { | ||||
|                 mime | ||||
|                     .get_param("charset") | ||||
|                     .map(|charset| charset.as_str()) | ||||
|             }) | ||||
|             .unwrap_or(default_encoding); | ||||
|         let encoding = Encoding::for_label(encoding_name.as_bytes()).unwrap_or(UTF_8); | ||||
|         Text { | ||||
|             concat: body.concat2(), | ||||
|             encoding | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Try to deserialize the response body as JSON using `serde`. | ||||
|     #[inline] | ||||
| @@ -261,6 +293,33 @@ impl<T> fmt::Debug for Json<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct Text { | ||||
|     concat: Concat2<Decoder>, | ||||
|     encoding: &'static Encoding, | ||||
| } | ||||
|  | ||||
| impl Future for Text { | ||||
|     type Item = String; | ||||
|     type Error = ::Error; | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         let bytes = try_ready!(self.concat.poll()); | ||||
|         // a block because of borrow checker | ||||
|         { | ||||
|             let (text, _, _) = self.encoding.decode(&bytes); | ||||
|             match text { | ||||
|                 Cow::Owned(s) => return Ok(Async::Ready(s)), | ||||
|                 _ => (), | ||||
|             } | ||||
|         } | ||||
|         unsafe { | ||||
|             // decoding returned Cow::Borrowed, meaning these bytes | ||||
|             // are already valid utf8 | ||||
|             Ok(Async::Ready(String::from_utf8_unchecked(bytes.to_vec()))) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone, PartialEq)] | ||||
| struct ResponseUrl(Url); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user