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