attohttpc/request/
session.rs

1use std::convert::TryInto;
2use std::sync::Arc;
3use std::time::Duration;
4
5use http::header::{HeaderValue, IntoHeaderName};
6use http::Method;
7
8#[cfg(feature = "charsets")]
9use crate::charsets::Charset;
10use crate::error::{Error, Result};
11use crate::request::proxy::ProxySettings;
12use crate::request::{BaseSettings, RequestBuilder};
13use crate::tls::Certificate;
14
15/// `Session` is a type that can carry settings over multiple requests. The settings applied to the
16/// `Session` are applied to every request created from this `Session`.
17///
18/// `Session` can be cloned cheaply and sent to other threads as it uses [std::sync::Arc] internally.
19#[derive(Clone, Debug, Default)]
20pub struct Session {
21    base_settings: Arc<BaseSettings>,
22}
23
24impl Session {
25    /// Create a new `Session` with default settings.
26    pub fn new() -> Session {
27        Session {
28            base_settings: Arc::new(BaseSettings::default()),
29        }
30    }
31
32    /// Create a new `RequestBuilder` with the GET method and this Session's settings applied on it.
33    pub fn get<U>(&self, base_url: U) -> RequestBuilder
34    where
35        U: AsRef<str>,
36    {
37        RequestBuilder::with_settings(Method::GET, base_url, self.base_settings.clone())
38    }
39
40    /// Create a new `RequestBuilder` with the POST method and this Session's settings applied on it.
41    pub fn post<U>(&self, base_url: U) -> RequestBuilder
42    where
43        U: AsRef<str>,
44    {
45        RequestBuilder::with_settings(Method::POST, base_url, self.base_settings.clone())
46    }
47
48    /// Create a new `RequestBuilder` with the PUT method and this Session's settings applied on it.
49    pub fn put<U>(&self, base_url: U) -> RequestBuilder
50    where
51        U: AsRef<str>,
52    {
53        RequestBuilder::with_settings(Method::PUT, base_url, self.base_settings.clone())
54    }
55
56    /// Create a new `RequestBuilder` with the DELETE method and this Session's settings applied on it.
57    pub fn delete<U>(&self, base_url: U) -> RequestBuilder
58    where
59        U: AsRef<str>,
60    {
61        RequestBuilder::with_settings(Method::DELETE, base_url, self.base_settings.clone())
62    }
63
64    /// Create a new `RequestBuilder` with the HEAD method and this Session's settings applied on it.
65    pub fn head<U>(&self, base_url: U) -> RequestBuilder
66    where
67        U: AsRef<str>,
68    {
69        RequestBuilder::with_settings(Method::HEAD, base_url, self.base_settings.clone())
70    }
71
72    /// Create a new `RequestBuilder` with the OPTIONS method and this Session's settings applied on it.
73    pub fn options<U>(&self, base_url: U) -> RequestBuilder
74    where
75        U: AsRef<str>,
76    {
77        RequestBuilder::with_settings(Method::OPTIONS, base_url, self.base_settings.clone())
78    }
79
80    /// Create a new `RequestBuilder` with the PATCH method and this Session's settings applied on it.
81    pub fn patch<U>(&self, base_url: U) -> RequestBuilder
82    where
83        U: AsRef<str>,
84    {
85        RequestBuilder::with_settings(Method::PATCH, base_url, self.base_settings.clone())
86    }
87
88    /// Create a new `RequestBuilder` with the TRACE method and this Session's settings applied on it.
89    pub fn trace<U>(&self, base_url: U) -> RequestBuilder
90    where
91        U: AsRef<str>,
92    {
93        RequestBuilder::with_settings(Method::TRACE, base_url, self.base_settings.clone())
94    }
95
96    //
97    // Settings
98    //
99
100    /// Modify a header for this `Session`.
101    ///
102    /// If the header is already present, the value will be replaced. If you wish to append a new header,
103    /// use `header_append`.
104    ///
105    /// # Panics
106    /// This method will panic if the value is invalid.
107    pub fn header<H, V>(&mut self, header: H, value: V)
108    where
109        H: IntoHeaderName,
110        V: TryInto<HeaderValue>,
111        Error: From<V::Error>,
112    {
113        self.try_header(header, value).expect("invalid header value");
114    }
115
116    /// Append a new header for this `Session`.
117    ///
118    /// The new header is always appended to the headers, even if the header already exists.
119    ///
120    /// # Panics
121    /// This method will panic if the value is invalid.
122    pub fn header_append<H, V>(&mut self, header: H, value: V)
123    where
124        H: IntoHeaderName,
125        V: TryInto<HeaderValue>,
126        Error: From<V::Error>,
127    {
128        self.try_header_append(header, value).expect("invalid header value");
129    }
130
131    /// Modify a header for this `Session`.
132    ///
133    /// If the header is already present, the value will be replaced. If you wish to append a new header,
134    /// use `header_append`.
135    pub fn try_header<H, V>(&mut self, header: H, value: V) -> Result<()>
136    where
137        H: IntoHeaderName,
138        V: TryInto<HeaderValue>,
139        Error: From<V::Error>,
140    {
141        self.base_settings.try_header(header, value)
142    }
143
144    /// Append a new header to this `Session`.
145    ///
146    /// The new header is always appended to the headers, even if the header already exists.
147    pub fn try_header_append<H, V>(&mut self, header: H, value: V) -> Result<()>
148    where
149        H: IntoHeaderName,
150        V: TryInto<HeaderValue>,
151        Error: From<V::Error>,
152    {
153        self.base_settings.try_header_append(header, value)
154    }
155
156    /// Set the maximum number of headers accepted in responses to requests created from this `Session`.
157    ///
158    /// The default is 100.
159    pub fn max_headers(&mut self, max_headers: usize) {
160        self.base_settings.set_max_headers(max_headers);
161    }
162
163    /// Set the maximum number of redirections the requests created from this `Session` can perform.
164    ///
165    /// The default is 5.
166    pub fn max_redirections(&mut self, max_redirections: u32) {
167        self.base_settings.set_max_redirections(max_redirections);
168    }
169
170    /// Sets if requests created from this `Session` should follow redirects, 3xx codes.
171    ///
172    /// This value defaults to true.
173    pub fn follow_redirects(&mut self, follow_redirects: bool) {
174        self.base_settings.set_follow_redirects(follow_redirects);
175    }
176
177    /// Sets a connect timeout for requests created from this `Session`.
178    ///
179    /// The default is 30 seconds.
180    pub fn connect_timeout(&mut self, connect_timeout: Duration) {
181        self.base_settings.set_connect_timeout(connect_timeout);
182    }
183
184    /// Sets a read timeout for requests created from this `Session`.
185    ///
186    /// The default is 30 seconds.
187    pub fn read_timeout(&mut self, read_timeout: Duration) {
188        self.base_settings.set_read_tmeout(read_timeout);
189    }
190
191    /// Sets a timeout for the maximum duration of requests created from this `Session`.
192    ///
193    /// Applies after a TCP connection is established. Defaults to no timeout.
194    pub fn timeout(&mut self, timeout: Duration) {
195        self.base_settings.set_timeout(Some(timeout));
196    }
197
198    /// Sets the proxy settigns for requests created from this `Session`.
199    ///
200    /// If left untouched, the defaults are to use system proxy settings found in environment variables.
201    pub fn proxy_settings(&mut self, proxy_settings: ProxySettings) {
202        self.base_settings.set_proxy_settings(proxy_settings);
203    }
204
205    /// Set the default charset to use while parsing the responses of requests created from this `Session`.
206    ///
207    /// If the response does not say which charset it uses, this charset will be used to decode the requests.
208    /// This value defaults to `None`, in which case ISO-8859-1 is used.
209    #[cfg(feature = "charsets")]
210    pub fn default_charset(&mut self, default_charset: Option<Charset>) {
211        self.base_settings.set_default_charset(default_charset);
212    }
213
214    /// Sets if requests created from this `Session` will announce that they accept compression.
215    ///
216    /// This value defaults to true. Note that this only lets the browser know that the requests support
217    /// compression, the server might choose not to compress the content.
218    #[cfg(feature = "flate2")]
219    pub fn allow_compression(&mut self, allow_compression: bool) {
220        self.base_settings.set_allow_compression(allow_compression);
221    }
222
223    /// Sets if requests created from this `Session` will accept invalid TLS certificates.
224    ///
225    /// Accepting invalid certificates implies that invalid hostnames are accepted
226    /// as well.
227    ///
228    /// The default value is `false`.
229    ///
230    /// # Danger
231    /// Use this setting with care. This will accept **any** TLS certificate valid or not.
232    /// If you are using self signed certificates, it is much safer to add their root CA
233    /// to the list of trusted root CAs by your system.
234    pub fn danger_accept_invalid_certs(&mut self, accept_invalid_certs: bool) {
235        self.base_settings.set_accept_invalid_certs(accept_invalid_certs);
236    }
237
238    /// Sets if requests created from this `Session` will accept an invalid hostname in a TLS certificate.
239    ///
240    /// The default value is `false`.
241    ///
242    /// # Danger
243    /// Use this setting with care. This will accept TLS certificates that do not match
244    /// the hostname.
245    pub fn danger_accept_invalid_hostnames(&mut self, accept_invalid_hostnames: bool) {
246        self.base_settings
247            .set_accept_invalid_hostnames(accept_invalid_hostnames);
248    }
249
250    /// Adds a root certificate that will be trusted by requests created from this `Session`.
251    pub fn add_root_certificate(&mut self, cert: Certificate) {
252        self.base_settings.add_root_certificate(cert);
253    }
254}