1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::convert::TryFrom; 15 use std::ops::{Deref, DerefMut}; 16 17 use ylong_http::body::async_impl::Body; 18 use ylong_http::body::MultiPart; 19 use ylong_http::error::HttpError; 20 use ylong_http::headers::{HeaderName, HeaderValue}; 21 use ylong_http::request::method::Method; 22 use ylong_http::request::uri::Uri; 23 use ylong_http::request::{Request, RequestBuilder as ReqBuilder}; 24 use ylong_http::response::Response as Resp; 25 use ylong_http::version::Version; 26 27 use crate::async_impl::HttpBody; 28 use crate::{ErrorKind, HttpClientError}; 29 30 /// Response Adapter. 31 pub struct Response { 32 response: Resp<HttpBody>, 33 } 34 35 impl Response { new(response: Resp<HttpBody>) -> Self36 pub(crate) fn new(response: Resp<HttpBody>) -> Self { 37 Self { response } 38 } 39 40 /// `text()` adapter. text(self) -> Result<String, HttpClientError>41 pub async fn text(self) -> Result<String, HttpClientError> { 42 let mut buf = [0u8; 1024]; 43 let mut vec = Vec::new(); 44 let mut response = self.response; 45 loop { 46 let size = response.body_mut().data(&mut buf).await?; 47 if size == 0 { 48 break; 49 } 50 vec.extend_from_slice(&buf[..size]); 51 } 52 String::from_utf8(vec).map_err(|_| { 53 HttpClientError::new_with_message( 54 ErrorKind::BodyDecode, 55 "The body content is not valid utf8.", 56 ) 57 }) 58 } 59 } 60 61 impl Deref for Response { 62 type Target = Resp<HttpBody>; 63 deref(&self) -> &Self::Target64 fn deref(&self) -> &Self::Target { 65 &self.response 66 } 67 } 68 69 impl DerefMut for Response { deref_mut(&mut self) -> &mut Self::Target70 fn deref_mut(&mut self) -> &mut Self::Target { 71 &mut self.response 72 } 73 } 74 75 /// RequestBuilder Adapter 76 pub struct RequestBuilder(ReqBuilder); 77 78 impl RequestBuilder { 79 /// Creates a new, default `RequestBuilder`. new() -> Self80 pub fn new() -> Self { 81 Self(ReqBuilder::new()) 82 } 83 84 /// Sets the `Method` of the `Request`. method<T>(self, method: T) -> Self where Method: TryFrom<T>, <Method as TryFrom<T>>::Error: Into<HttpError>,85 pub fn method<T>(self, method: T) -> Self 86 where 87 Method: TryFrom<T>, 88 <Method as TryFrom<T>>::Error: Into<HttpError>, 89 { 90 Self(self.0.method(method)) 91 } 92 93 /// Sets the `Uri` of the `Request`. `Uri` does not provide a default value, 94 /// so it must be set. url<T>(self, uri: T) -> Self where Uri: TryFrom<T>, <Uri as TryFrom<T>>::Error: Into<HttpError>,95 pub fn url<T>(self, uri: T) -> Self 96 where 97 Uri: TryFrom<T>, 98 <Uri as TryFrom<T>>::Error: Into<HttpError>, 99 { 100 Self(self.0.url(uri)) 101 } 102 103 /// Sets the `Version` of the `Request`. Uses `Version::HTTP11` by default. version<T>(mut self, version: T) -> Self where Version: TryFrom<T>, <Version as TryFrom<T>>::Error: Into<HttpError>,104 pub fn version<T>(mut self, version: T) -> Self 105 where 106 Version: TryFrom<T>, 107 <Version as TryFrom<T>>::Error: Into<HttpError>, 108 { 109 self.0 = self.0.version(version); 110 self 111 } 112 113 /// Adds a `Header` to `Request`. Overwrites `HeaderValue` if the 114 /// `HeaderName` already exists. 115 /// 116 /// # Examples 117 /// 118 /// ``` 119 /// use ylong_http::headers::Headers; 120 /// use ylong_http::request::RequestBuilder; 121 /// 122 /// let request = RequestBuilder::new().header("ACCEPT", "text/html"); 123 /// ``` header<N, V>(mut self, name: N, value: V) -> Self where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,124 pub fn header<N, V>(mut self, name: N, value: V) -> Self 125 where 126 HeaderName: TryFrom<N>, 127 <HeaderName as TryFrom<N>>::Error: Into<HttpError>, 128 HeaderValue: TryFrom<V>, 129 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>, 130 { 131 self.0 = self.0.header(name, value); 132 self 133 } 134 135 /// Adds a `Header` to `Request`. Appends `HeaderValue` to the end of 136 /// previous `HeaderValue` if the `HeaderName` already exists. 137 /// 138 /// # Examples 139 /// 140 /// ``` 141 /// use ylong_http::headers::Headers; 142 /// use ylong_http::request::RequestBuilder; 143 /// 144 /// let request = RequestBuilder::new().append_header("ACCEPT", "text/html"); 145 /// ``` append_header<N, V>(mut self, name: N, value: V) -> Self where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,146 pub fn append_header<N, V>(mut self, name: N, value: V) -> Self 147 where 148 HeaderName: TryFrom<N>, 149 <HeaderName as TryFrom<N>>::Error: Into<HttpError>, 150 HeaderValue: TryFrom<V>, 151 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>, 152 { 153 self.0 = self.0.append_header(name, value); 154 self 155 } 156 157 /// Try to create a `Request` based on the incoming `body`. body<T>(self, body: T) -> Result<Request<T>, HttpClientError>158 pub fn body<T>(self, body: T) -> Result<Request<T>, HttpClientError> { 159 self.0 160 .body(body) 161 .map_err(|e| HttpClientError::new_with_cause(ErrorKind::Build, Some(e))) 162 } 163 164 /// Creates a `Request` that uses this `RequestBuilder` configuration and 165 /// the provided `Multipart`. You can also provide a `Uploader<Multipart>` 166 /// as the body. 167 /// 168 /// # Error 169 /// 170 /// This method fails if some configurations are wrong. multipart<T>(self, body: T) -> Result<Request<T>, HttpClientError> where T: AsRef<MultiPart>,171 pub fn multipart<T>(self, body: T) -> Result<Request<T>, HttpClientError> 172 where 173 T: AsRef<MultiPart>, 174 { 175 self.0 176 .multipart(body) 177 .map_err(|e| HttpClientError::new_with_cause(ErrorKind::Build, Some(e))) 178 } 179 } 180 181 impl Default for RequestBuilder { default() -> Self182 fn default() -> Self { 183 Self::new() 184 } 185 } 186