1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! HTTP client configuration for schema retrieval.
use std::{path::PathBuf, time::Duration};
/// Configuration options for HTTP client used in schema retrieval.
///
/// This struct provides builder-style methods to configure the HTTP client
/// used when fetching external schemas via HTTP/HTTPS.
///
/// # Example
///
/// ```rust
/// use std::time::Duration;
/// use jsonschema::HttpOptions;
///
/// let http_options = HttpOptions::new()
/// .connect_timeout(Duration::from_secs(10))
/// .timeout(Duration::from_secs(30))
/// .danger_accept_invalid_certs(false);
/// ```
#[derive(Debug, Clone, Default)]
pub struct HttpOptions {
pub(crate) connect_timeout: Option<Duration>,
pub(crate) timeout: Option<Duration>,
pub(crate) danger_accept_invalid_certs: bool,
pub(crate) root_certificate: Option<PathBuf>,
}
impl HttpOptions {
/// Create a new `HttpOptions` with default settings.
#[must_use]
pub fn new() -> Self {
Self::default()
}
/// Set the timeout for the connect phase of a connection.
///
/// This controls how long the client will wait to establish a connection
/// to the remote server.
///
/// # Example
///
/// ```rust
/// use std::time::Duration;
/// use jsonschema::HttpOptions;
///
/// let options = HttpOptions::new()
/// .connect_timeout(Duration::from_secs(10));
/// ```
#[must_use]
pub fn connect_timeout(mut self, timeout: Duration) -> Self {
self.connect_timeout = Some(timeout);
self
}
/// Set the total timeout for the entire request.
///
/// This includes connection time, any redirects, and reading the response body.
///
/// **Note**: If `timeout` is smaller than `connect_timeout`, the total timeout
/// takes precedence and will cap the connection attempt.
///
/// # Example
///
/// ```rust
/// use std::time::Duration;
/// use jsonschema::HttpOptions;
///
/// let options = HttpOptions::new()
/// .timeout(Duration::from_secs(60));
/// ```
#[must_use]
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
/// Controls whether to accept invalid TLS certificates.
///
/// **WARNING**: Setting this to `true` disables certificate validation,
/// which makes the connection vulnerable to man-in-the-middle attacks.
/// Only use this for testing or in controlled environments.
///
/// # Example
///
/// ```rust
/// use jsonschema::HttpOptions;
///
/// // Not recommended for production use!
/// let options = HttpOptions::new()
/// .danger_accept_invalid_certs(true);
/// ```
#[must_use]
pub fn danger_accept_invalid_certs(mut self, accept: bool) -> Self {
self.danger_accept_invalid_certs = accept;
self
}
/// Add a custom root certificate for TLS verification.
///
/// This allows you to trust a custom CA certificate in addition to
/// the system's root certificates.
///
/// # Example
///
/// ```rust
/// use std::path::PathBuf;
/// use jsonschema::HttpOptions;
///
/// let options = HttpOptions::new()
/// .add_root_certificate("/path/to/ca-cert.pem");
/// ```
#[must_use]
pub fn add_root_certificate(mut self, path: impl Into<PathBuf>) -> Self {
self.root_certificate = Some(path.into());
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_methods() {
let options = HttpOptions::new()
.connect_timeout(Duration::from_secs(10))
.timeout(Duration::from_secs(30))
.danger_accept_invalid_certs(true)
.add_root_certificate("/path/to/cert.pem");
assert_eq!(options.connect_timeout, Some(Duration::from_secs(10)));
assert_eq!(options.timeout, Some(Duration::from_secs(30)));
assert!(options.danger_accept_invalid_certs);
assert_eq!(
options.root_certificate,
Some(PathBuf::from("/path/to/cert.pem"))
);
}
}