1use std::{rc::Rc, time::Duration};
4
5use actix_http::{error::HttpError, header::HeaderMap, Method, RequestHead, Uri};
6use actix_rt::net::TcpStream;
7use actix_service::Service;
8pub use actix_tls::connect::{
9 ConnectError as TcpConnectError, ConnectInfo, Connection as TcpConnection,
10};
11
12use crate::{ws, BoxConnectorService, ClientBuilder, ClientRequest};
13
14mod config;
15mod connection;
16mod connector;
17mod error;
18mod h1proto;
19mod h2proto;
20mod pool;
21
22pub use self::{
23 connection::{Connection, ConnectionIo},
24 connector::{Connector, ConnectorService},
25 error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError},
26};
27
28#[derive(Clone)]
29pub struct Connect {
30 pub uri: Uri,
31 pub addr: Option<std::net::SocketAddr>,
32}
33
34#[derive(Clone)]
56pub struct Client(pub(crate) ClientConfig);
57
58#[derive(Clone)]
59pub(crate) struct ClientConfig {
60 pub(crate) connector: BoxConnectorService,
61 pub(crate) default_headers: Rc<HeaderMap>,
62 pub(crate) timeout: Option<Duration>,
63}
64
65impl Default for Client {
66 fn default() -> Self {
67 ClientBuilder::new().finish()
68 }
69}
70
71impl Client {
72 pub fn new() -> Client {
74 Client::default()
75 }
76
77 pub fn builder() -> ClientBuilder<
81 impl Service<
82 ConnectInfo<Uri>,
83 Response = TcpConnection<Uri, TcpStream>,
84 Error = TcpConnectError,
85 > + Clone,
86 > {
87 ClientBuilder::new()
88 }
89
90 pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
92 where
93 Uri: TryFrom<U>,
94 <Uri as TryFrom<U>>::Error: Into<HttpError>,
95 {
96 let mut req = ClientRequest::new(method, url, self.0.clone());
97
98 for header in self.0.default_headers.iter() {
99 req = req.append_header(header);
100 }
101
102 req
103 }
104
105 pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
110 where
111 Uri: TryFrom<U>,
112 <Uri as TryFrom<U>>::Error: Into<HttpError>,
113 {
114 let mut req = self.request(head.method.clone(), url);
115 for header in head.headers.iter() {
116 req = req.insert_header_if_none(header);
117 }
118 req
119 }
120
121 pub fn get<U>(&self, url: U) -> ClientRequest
123 where
124 Uri: TryFrom<U>,
125 <Uri as TryFrom<U>>::Error: Into<HttpError>,
126 {
127 self.request(Method::GET, url)
128 }
129
130 pub fn head<U>(&self, url: U) -> ClientRequest
132 where
133 Uri: TryFrom<U>,
134 <Uri as TryFrom<U>>::Error: Into<HttpError>,
135 {
136 self.request(Method::HEAD, url)
137 }
138
139 pub fn put<U>(&self, url: U) -> ClientRequest
141 where
142 Uri: TryFrom<U>,
143 <Uri as TryFrom<U>>::Error: Into<HttpError>,
144 {
145 self.request(Method::PUT, url)
146 }
147
148 pub fn post<U>(&self, url: U) -> ClientRequest
150 where
151 Uri: TryFrom<U>,
152 <Uri as TryFrom<U>>::Error: Into<HttpError>,
153 {
154 self.request(Method::POST, url)
155 }
156
157 pub fn patch<U>(&self, url: U) -> ClientRequest
159 where
160 Uri: TryFrom<U>,
161 <Uri as TryFrom<U>>::Error: Into<HttpError>,
162 {
163 self.request(Method::PATCH, url)
164 }
165
166 pub fn delete<U>(&self, url: U) -> ClientRequest
168 where
169 Uri: TryFrom<U>,
170 <Uri as TryFrom<U>>::Error: Into<HttpError>,
171 {
172 self.request(Method::DELETE, url)
173 }
174
175 pub fn options<U>(&self, url: U) -> ClientRequest
177 where
178 Uri: TryFrom<U>,
179 <Uri as TryFrom<U>>::Error: Into<HttpError>,
180 {
181 self.request(Method::OPTIONS, url)
182 }
183
184 pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
187 where
188 Uri: TryFrom<U>,
189 <Uri as TryFrom<U>>::Error: Into<HttpError>,
190 {
191 let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
192 for (key, value) in self.0.default_headers.iter() {
193 req.head.headers.insert(key.clone(), value.clone());
194 }
195 req
196 }
197
198 pub fn headers(&mut self) -> Option<&mut HeaderMap> {
203 Rc::get_mut(&mut self.0.default_headers)
204 }
205}