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::io::{Read, Write}; 15 16 use ylong_http::body::sync_impl::Body; 17 use ylong_http::h1::{RequestEncoder, ResponseDecoder}; 18 use ylong_http::request::Request; 19 use ylong_http::response::Response; 20 21 use crate::error::{ErrorKind, HttpClientError}; 22 use crate::sync_impl::conn::StreamData; 23 use crate::sync_impl::HttpBody; 24 use crate::util::dispatcher::http1::Http1Conn; 25 26 const TEMP_BUF_SIZE: usize = 16 * 1024; 27 28 pub(crate) fn request<S, T>( 29 mut conn: Http1Conn<S>, 30 request: &mut Request<T>, 31 ) -> Result<Response<HttpBody>, HttpClientError> 32 where 33 T: Body, 34 S: Read + Write + 'static, 35 { 36 let mut buf = vec![0u8; TEMP_BUF_SIZE]; 37 38 // Encodes request. 39 let mut encode_part = Some(RequestEncoder::new(request.part().clone())); 40 let mut encode_body = Some(request.body_mut()); 41 let mut write = 0; 42 while encode_part.is_some() || encode_body.is_some() { 43 if write < buf.len() { 44 if let Some(part) = encode_part.as_mut() { 45 let size = part 46 .encode(&mut buf[write..]) 47 .map_err(|e| HttpClientError::from_error(ErrorKind::Request, e))?; 48 write += size; 49 if size == 0 { 50 encode_part = None; 51 } 52 } 53 } 54 55 if write < buf.len() { 56 if let Some(body) = encode_body.as_mut() { 57 let size = body 58 .data(&mut buf[write..]) 59 .map_err(|e| HttpClientError::from_error(ErrorKind::BodyTransfer, e))?; 60 write += size; 61 if size == 0 { 62 encode_body = None; 63 } 64 } 65 } 66 67 if write == buf.len() { 68 conn.raw_mut() 69 .write_all(&buf[..write]) 70 .map_err(|e| HttpClientError::from_error(ErrorKind::Request, e))?; 71 write = 0; 72 } 73 } 74 75 if write != 0 { 76 conn.raw_mut() 77 .write_all(&buf[..write]) 78 .map_err(|e| HttpClientError::from_error(ErrorKind::Request, e))?; 79 } 80 81 // Decodes response part. 82 let (part, pre) = { 83 let mut decoder = ResponseDecoder::new(); 84 loop { 85 let size = conn 86 .raw_mut() 87 .read(buf.as_mut_slice()) 88 .map_err(|e| HttpClientError::from_error(ErrorKind::Request, e))?; 89 match decoder.decode(&buf[..size]) { 90 Ok(None) => {} 91 Ok(Some((part, rem))) => break (part, rem), 92 Err(e) => return err_from_other!(Request, e), 93 } 94 } 95 }; 96 97 // Generates response body. 98 let body = { 99 let chunked = part 100 .headers 101 .get("Transfer-Encoding") 102 .map(|v| v.to_string().unwrap_or(String::new())) 103 .and_then(|s| s.find("chunked")) 104 .is_some(); 105 let content_length = part 106 .headers 107 .get("Content-Length") 108 .map(|v| v.to_string().unwrap_or(String::new())) 109 .and_then(|s| s.parse::<u64>().ok()); 110 111 let is_trailer = part.headers.get("Trailer").is_some(); 112 113 match (chunked, content_length, pre.is_empty()) { 114 (true, None, _) => HttpBody::chunk(pre, Box::new(conn), is_trailer), 115 (false, Some(len), _) => HttpBody::text(len, pre, Box::new(conn)), 116 (false, None, true) => HttpBody::empty(), 117 _ => { 118 return err_from_msg!(Request, "Invalid response format"); 119 } 120 } 121 }; 122 Ok(Response::from_raw_parts(part, body)) 123 } 124 125 impl<S: Read> Read for Http1Conn<S> { readnull126 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { 127 self.raw_mut().read(buf) 128 } 129 } 130 131 impl<S: Read> StreamData for Http1Conn<S> { shutdownnull132 fn shutdown(&self) { 133 Self::shutdown(self) 134 } 135 } 136