1 use std::fmt; 2 3 use bytes::Bytes; 4 use http::{HeaderMap, StatusCode}; 5 use js_sys::Uint8Array; 6 use url::Url; 7 8 #[cfg(feature = "json")] 9 use serde::de::DeserializeOwned; 10 11 /// A Response to a submitted `Request`. 12 pub struct Response { 13 http: http::Response<web_sys::Response>, 14 // Boxed to save space (11 words to 1 word), and it's not accessed 15 // frequently internally. 16 url: Box<Url>, 17 } 18 19 impl Response { new(res: http::Response<web_sys::Response>, url: Url) -> Response20 pub(super) fn new(res: http::Response<web_sys::Response>, url: Url) -> Response { 21 Response { 22 http: res, 23 url: Box::new(url), 24 } 25 } 26 27 /// Get the `StatusCode` of this `Response`. 28 #[inline] status(&self) -> StatusCode29 pub fn status(&self) -> StatusCode { 30 self.http.status() 31 } 32 33 /// Get the `Headers` of this `Response`. 34 #[inline] headers(&self) -> &HeaderMap35 pub fn headers(&self) -> &HeaderMap { 36 self.http.headers() 37 } 38 39 /// Get a mutable reference to the `Headers` of this `Response`. 40 #[inline] headers_mut(&mut self) -> &mut HeaderMap41 pub fn headers_mut(&mut self) -> &mut HeaderMap { 42 self.http.headers_mut() 43 } 44 45 /// Get the content-length of this response, if known. 46 /// 47 /// Reasons it may not be known: 48 /// 49 /// - The server didn't send a `content-length` header. 50 /// - The response is compressed and automatically decoded (thus changing 51 /// the actual decoded length). content_length(&self) -> Option<u64>52 pub fn content_length(&self) -> Option<u64> { 53 self.headers() 54 .get(http::header::CONTENT_LENGTH)? 55 .to_str() 56 .ok()? 57 .parse() 58 .ok() 59 } 60 61 /// Get the final `Url` of this `Response`. 62 #[inline] url(&self) -> &Url63 pub fn url(&self) -> &Url { 64 &self.url 65 } 66 67 /* It might not be possible to detect this in JS? 68 /// Get the HTTP `Version` of this `Response`. 69 #[inline] 70 pub fn version(&self) -> Version { 71 self.http.version() 72 } 73 */ 74 75 /// Try to deserialize the response body as JSON. 76 #[cfg(feature = "json")] 77 #[cfg_attr(docsrs, doc(cfg(feature = "json")))] json<T: DeserializeOwned>(self) -> crate::Result<T>78 pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> { 79 let full = self.bytes().await?; 80 81 serde_json::from_slice(&full).map_err(crate::error::decode) 82 } 83 84 /// Get the response text. text(self) -> crate::Result<String>85 pub async fn text(self) -> crate::Result<String> { 86 let p = self 87 .http 88 .body() 89 .text() 90 .map_err(crate::error::wasm) 91 .map_err(crate::error::decode)?; 92 let js_val = super::promise::<wasm_bindgen::JsValue>(p) 93 .await 94 .map_err(crate::error::decode)?; 95 if let Some(s) = js_val.as_string() { 96 Ok(s) 97 } else { 98 Err(crate::error::decode("response.text isn't string")) 99 } 100 } 101 102 /// Get the response as bytes bytes(self) -> crate::Result<Bytes>103 pub async fn bytes(self) -> crate::Result<Bytes> { 104 let p = self 105 .http 106 .body() 107 .array_buffer() 108 .map_err(crate::error::wasm) 109 .map_err(crate::error::decode)?; 110 111 let buf_js = super::promise::<wasm_bindgen::JsValue>(p) 112 .await 113 .map_err(crate::error::decode)?; 114 115 let buffer = Uint8Array::new(&buf_js); 116 let mut bytes = vec![0; buffer.length() as usize]; 117 buffer.copy_to(&mut bytes); 118 Ok(bytes.into()) 119 } 120 121 // util methods 122 123 /// Turn a response into an error if the server returned an error. error_for_status(self) -> crate::Result<Self>124 pub fn error_for_status(self) -> crate::Result<Self> { 125 let status = self.status(); 126 if status.is_client_error() || status.is_server_error() { 127 Err(crate::error::status_code(*self.url, status)) 128 } else { 129 Ok(self) 130 } 131 } 132 133 /// Turn a reference to a response into an error if the server returned an error. error_for_status_ref(&self) -> crate::Result<&Self>134 pub fn error_for_status_ref(&self) -> crate::Result<&Self> { 135 let status = self.status(); 136 if status.is_client_error() || status.is_server_error() { 137 Err(crate::error::status_code(*self.url.clone(), status)) 138 } else { 139 Ok(self) 140 } 141 } 142 } 143 144 impl fmt::Debug for Response { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 146 f.debug_struct("Response") 147 //.field("url", self.url()) 148 .field("status", &self.status()) 149 .field("headers", self.headers()) 150 .finish() 151 } 152 } 153