http_quik/client/
response.rs1use bytes::Bytes;
2use http::header::{HeaderMap, CONTENT_ENCODING};
3use http::{Response as HttpResponse, StatusCode};
4use http2::RecvStream;
5use std::io::Read;
6
7use crate::error::{Error, Result};
8
9pub struct Response {
14 inner: HttpResponse<RecvStream>,
16 url: String,
18}
19
20impl Response {
21 pub fn new(inner: HttpResponse<RecvStream>, url: String) -> Self {
23 Self { inner, url }
24 }
25
26 pub fn status(&self) -> StatusCode {
28 self.inner.status()
29 }
30
31 pub fn headers(&self) -> &HeaderMap {
33 self.inner.headers()
34 }
35
36 pub fn url(&self) -> &str {
38 &self.url
39 }
40
41 pub(crate) fn set_url(&mut self, url: String) {
43 self.url = url;
44 }
45
46 pub async fn bytes(self) -> Result<Bytes> {
51 let (parts, mut body_stream) = self.inner.into_parts();
52 let mut data = Vec::new();
53
54 while let Some(chunk) = body_stream.data().await {
55 let chunk = chunk.map_err(Error::Http2)?;
56 data.extend_from_slice(chunk.as_ref());
57 }
58
59 let encoding = parts
60 .headers
61 .get(CONTENT_ENCODING)
62 .and_then(|v| v.to_str().ok())
63 .unwrap_or("");
64
65 if encoding.contains("br") {
66 let mut decoder = brotli_decompressor::Decompressor::new(&data[..], 4096);
67 let mut decoded = Vec::new();
68 decoder
69 .read_to_end(&mut decoded)
70 .map_err(|e| Error::Connect(std::io::Error::other(e.to_string())))?;
71 Ok(Bytes::from(decoded))
72 } else if encoding.contains("zstd") {
73 let decoded = zstd::decode_all(&data[..])
74 .map_err(|e| Error::Connect(std::io::Error::other(e.to_string())))?;
75 Ok(Bytes::from(decoded))
76 } else if encoding.contains("gzip") {
77 let mut decoder = flate2::read::GzDecoder::new(&data[..]);
78 let mut decoded = Vec::new();
79 decoder
80 .read_to_end(&mut decoded)
81 .map_err(|e| Error::Connect(std::io::Error::other(e.to_string())))?;
82 Ok(Bytes::from(decoded))
83 } else {
84 Ok(Bytes::from(data))
85 }
86 }
87
88 pub async fn text(self) -> Result<String> {
90 let bytes = self.bytes().await?;
91 String::from_utf8(bytes.to_vec())
92 .map_err(|e| Error::Connect(std::io::Error::other(e.to_string())))
93 }
94
95 pub async fn json<T: serde::de::DeserializeOwned>(self) -> Result<T> {
97 let bytes = self.bytes().await?;
98 serde_json::from_slice(&bytes)
99 .map_err(|e| Error::Connect(std::io::Error::other(e.to_string())))
100 }
101}