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