Add Response::text() to async Client

This commit is contained in:
messense
2019-06-23 14:39:41 +08:00
committed by Sean McArthur
parent a3cd3633d8
commit c5f2bf6c32
2 changed files with 95 additions and 0 deletions

View File

@@ -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);