httpmock/common/
data.rs

1extern crate serde_regex;
2
3use crate::{
4    common::{
5        data::Error::{
6            HeaderDeserializationError, RequestConversionError, StaticMockConversionError,
7        },
8        util::HttpMockBytes,
9    },
10    server::matchers::generic::MatchingStrategy,
11};
12use bytes::Bytes;
13use serde::{Deserialize, Serialize};
14use serde_json::Value;
15use std::{
16    cmp::Ordering,
17    collections::HashMap,
18    convert::{TryFrom, TryInto},
19    fmt,
20    fmt::Debug,
21    str::FromStr,
22    sync::Arc,
23};
24use url::Url;
25
26use crate::server::RequestMetadata;
27#[cfg(feature = "cookies")]
28use headers::{Cookie, HeaderMapExt};
29
30#[derive(thiserror::Error, Debug)]
31pub enum Error {
32    #[error("Cannot deserialize header: {0}")]
33    HeaderDeserializationError(String),
34    #[error("Cookie parser error: {0}")]
35    CookieParserError(String),
36    #[error("cannot convert to/from static mock: {0}")]
37    StaticMockConversionError(String),
38    #[error("JSONConversionError: {0}")]
39    JSONConversionError(#[from] serde_json::Error),
40    #[error("Invalid request data: {0}")]
41    InvalidRequestData(String),
42    #[error("Cannot convert request to/from internal structure: {0}")]
43    RequestConversionError(String),
44}
45
46/// A general abstraction of an HTTP request of `httpmock`.
47#[derive(Serialize, Deserialize, Debug, Clone)]
48pub struct HttpMockRequest {
49    scheme: String,
50    uri: String,
51    method: String,
52    headers: Vec<(String, String)>,
53    version: String,
54    body: HttpMockBytes,
55}
56
57impl HttpMockRequest {
58    pub(crate) fn new(
59        scheme: String,
60        uri: String,
61        method: String,
62        headers: Vec<(String, String)>,
63        version: String,
64        body: HttpMockBytes,
65    ) -> Self {
66        // TODO: Many fields from the struct are exposed as structures from http package to the user.
67        //  These values here are also converted to these http crate structures every call.
68        //  ==> Convert these values here into http crate structures and allow returning an error
69        //      here instead of "unwrap" all the time later (see functions below).
70        //      Convert into http crate structures once here and store the converted
71        //          values in the struct instance here rather than only String values everywhere.
72        //     This will require to make the HttpMockRequest serde compatible
73        //     (http types are not serializable by default).
74        Self {
75            scheme,
76            uri,
77            method,
78            headers,
79            version,
80            body,
81        }
82    }
83
84    /// Parses and returns the URI of the request.
85    ///
86    /// # Attention
87    ///
88    /// - This method returns the full URI of the request as an `http::Uri` object.
89    /// - The URI returned by this method does not include the `Host` part. In HTTP/1.1,
90    ///   the request line typically contains only the path and query, not the full URL with the host.
91    /// - To retrieve the host, you should use the `HttpMockRequest::host` method which extracts the `Host`
92    ///   header (for HTTP/1.1) or the `:authority` pseudo-header (for HTTP/2 and HTTP/3).
93    ///
94    /// # Returns
95    ///
96    /// An `http::Uri` object representing the full URI of the request.
97    pub fn uri(&self) -> http::Uri {
98        self.uri.parse().unwrap()
99    }
100
101    /// Parses the scheme from the request.
102    ///
103    /// This function extracts the scheme (protocol) used in the request. If the request contains a relative path,
104    /// the scheme will be inferred based on how the server received the request. For instance, if the request was
105    /// sent to the server using HTTPS, the scheme will be set to "https"; otherwise, it will be set to "http".
106    ///
107    /// # Returns
108    ///
109    /// A `String` representing the scheme of the request, either "https" or "http".
110    pub fn scheme(&self) -> String {
111        let uri = self.uri();
112        if let Some(scheme) = uri.scheme() {
113            return scheme.to_string();
114        }
115
116        self.scheme.clone()
117    }
118
119    /// Returns the URI of the request as a string slice.
120    ///
121    /// # Attention
122    ///
123    /// - This method returns the full URI as a string slice.
124    /// - The URI string returned by this method does not include the `Host` part. In HTTP/1.1,
125    ///   the request line typically contains only the path and query, not the full URL with the host.
126    /// - To retrieve the host, you should use the `host` method which extracts the `Host`
127    ///   header (for HTTP/1.1) or the `:authority` pseudo-header (for HTTP/2 and HTTP/3).
128    ///
129    /// # Returns
130    ///
131    /// A string slice representing the full URI of the request.
132    pub fn uri_str(&self) -> &str {
133        self.uri.as_ref()
134    }
135
136    /// Returns the host that the request was sent to, based on the `Host` header or `:authority` pseudo-header.
137    ///
138    /// # Attention
139    ///
140    /// - This method retrieves the host from the `Host` header of the HTTP request for HTTP/1.1 requests.
141    ///   For HTTP/2 and HTTP/3 requests, it retrieves the host from the `:authority` pseudo-header.
142    /// - If you use the `HttpMockRequest::uri` method to get the full URI, note that
143    ///   the URI might not include the host part. In HTTP/1.1, the request line
144    ///   typically contains only the path and query, not the full URL.
145    ///
146    /// # Returns
147    ///
148    /// An `Option<String>` containing the host if the `Host` header or `:authority` pseudo-header is present, or
149    /// `None` if neither is found.
150    pub fn host(&self) -> Option<String> {
151        // Check the Host header first (HTTP 1.1)
152        if let Some((_, host)) = self
153            .headers
154            .iter()
155            .find(|&&(ref k, _)| k.eq_ignore_ascii_case("host"))
156        {
157            return Some(host.split(':').next().unwrap().to_string());
158        }
159
160        // If Host header is not found, check the URI authority (HTTP/2 and HTTP/3)
161        let uri = self.uri();
162        if let Some(authority) = uri.authority() {
163            return Some(authority.as_str().split(':').next().unwrap().to_string());
164        }
165
166        None
167    }
168
169    /// Returns the port that the request was sent to, based on the `Host` header or `:authority` pseudo-header.
170    ///
171    /// # Attention
172    ///
173    /// 1. This method retrieves the port from the `Host` header of the HTTP request for HTTP/1.1 requests.
174    ///    For HTTP/2 and HTTP/3 requests, it retrieves the port from the `:authority` pseudo-header.
175    ///    This method attempts to parse the port as a `u16`. If the port cannot be parsed as a `u16`, this method will continue as if the port was not specified (see point 2).
176    /// 2. If the port is not specified in the `Host` header or `:authority` pseudo-header, this method will return 443 (https) or 80 (http) based on the used scheme.
177    ///
178    /// # Returns
179    ///
180    /// An `u16` containing the port if the `Host` header or `:authority` pseudo-header is present and includes a valid port,
181    /// or 443 (https) or 80 (http) based on the used scheme otherwise.
182    pub fn port(&self) -> u16 {
183        // Check the Host header first (HTTP 1.1)
184        if let Some((_, host)) = self
185            .headers
186            .iter()
187            .find(|&&(ref k, _)| k.eq_ignore_ascii_case("host"))
188        {
189            if let Some(port_str) = host.split(':').nth(1) {
190                if let Ok(port) = port_str.parse::<u16>() {
191                    return port;
192                }
193            }
194        }
195
196        // If Host header is not found, check the URI authority (HTTP/2 and HTTP/3)
197        let uri = self.uri();
198        if let Some(authority) = uri.authority() {
199            if let Some(port_str) = authority.as_str().split(':').nth(1) {
200                if let Ok(port) = port_str.parse::<u16>() {
201                    return port;
202                }
203            }
204        }
205
206        if self.scheme().eq("https") {
207            return 443;
208        }
209
210        return 80;
211    }
212
213    pub fn method(&self) -> http::Method {
214        http::Method::from_bytes(self.method.as_bytes()).unwrap()
215    }
216
217    pub fn method_str(&self) -> &str {
218        self.method.as_ref()
219    }
220
221    pub fn headers(&self) -> http::HeaderMap<http::HeaderValue> {
222        let mut header_map: http::HeaderMap<http::HeaderValue> = http::HeaderMap::new();
223        for (key, value) in &self.headers {
224            let header_name = http::HeaderName::from_bytes(key.as_bytes()).unwrap();
225            let header_value = http::HeaderValue::from_str(&value).unwrap();
226
227            header_map.insert(header_name, header_value);
228        }
229
230        header_map
231    }
232
233    pub fn headers_vec(&self) -> &Vec<(String, String)> {
234        self.headers.as_ref()
235    }
236
237    pub fn query_params(&self) -> HashMap<String, String> {
238        self.query_params_vec().into_iter().collect()
239    }
240
241    pub fn query_params_vec(&self) -> Vec<(String, String)> {
242        // There doesn't seem to be a way to just parse Query string with `url` crate, so we're
243        // prefixing a dummy URL for parsing.
244        let url = format!("http://dummy?{}", self.uri().query().unwrap_or(""));
245        let url = Url::parse(&url).unwrap();
246
247        url.query_pairs()
248            .map(|(k, v)| (k.into_owned(), v.into_owned()))
249            .collect()
250    }
251
252    pub fn body(&self) -> &HttpMockBytes {
253        &self.body
254    }
255
256    pub fn body_string(&self) -> String {
257        self.body.to_string()
258    }
259
260    pub fn body_ref<'a>(&'a self) -> &'a [u8] {
261        self.body.as_ref()
262    }
263
264    // Move all body functions to HttpMockBytes
265    pub fn body_vec(&self) -> Vec<u8> {
266        self.body.to_vec()
267    }
268
269    pub fn body_bytes(&self) -> bytes::Bytes {
270        self.body.to_bytes()
271    }
272
273    pub fn version(&self) -> http::Version {
274        match self.version.as_ref() {
275            "HTTP/0.9" => http::Version::HTTP_09,
276            "HTTP/1.0" => http::Version::HTTP_10,
277            "HTTP/1.1" => http::Version::HTTP_11,
278            "HTTP/2.0" => http::Version::HTTP_2,
279            "HTTP/3.0" => http::Version::HTTP_3,
280            // Attention: This scenario is highly unlikely, so we panic here for the users
281            // convenience (user does not need to deal with errors for this reason alone).
282            _ => panic!("unknown HTTP version: {:?}", self.version),
283        }
284    }
285
286    pub fn version_ref(&self) -> &str {
287        self.version.as_ref()
288    }
289
290    #[cfg(feature = "cookies")]
291    pub(crate) fn cookies(&self) -> Result<Vec<(String, String)>, Error> {
292        let mut result = Vec::new();
293
294        if let Some(cookie) = self.headers().typed_get::<Cookie>() {
295            for (key, value) in cookie.iter() {
296                result.push((key.to_string(), value.to_string()));
297            }
298        }
299
300        Ok(result)
301    }
302
303    pub fn to_http_request(&self) -> http::Request<Bytes> {
304        self.try_into().unwrap()
305    }
306}
307
308fn http_headers_to_vec<T>(req: &http::Request<T>) -> Result<Vec<(String, String)>, Error> {
309    req.headers()
310        .iter()
311        .map(|(name, value)| {
312            // Attempt to convert the HeaderValue to a &str, returning an error if it fails.
313            let value_str = value
314                .to_str()
315                .map_err(|e| RequestConversionError(e.to_string()))?;
316            Ok((name.as_str().to_string(), value_str.to_string()))
317        })
318        .collect()
319}
320
321impl TryInto<http::Request<Bytes>> for &HttpMockRequest {
322    type Error = Error;
323
324    fn try_into(self) -> Result<http::Request<Bytes>, Self::Error> {
325        let mut builder = http::Request::builder()
326            .method(self.method())
327            .uri(self.uri())
328            .version(self.version());
329
330        for (k, v) in self.headers() {
331            builder = builder.header(k.map_or(String::new(), |v| v.to_string()), v)
332        }
333
334        let req = builder
335            .body(self.body().to_bytes())
336            .map_err(|err| RequestConversionError(err.to_string()))?;
337
338        Ok(req)
339    }
340}
341
342impl TryFrom<&http::Request<Bytes>> for HttpMockRequest {
343    type Error = Error;
344
345    fn try_from(value: &http::Request<Bytes>) -> Result<Self, Self::Error> {
346        let metadata = value
347            .extensions()
348            .get::<RequestMetadata>()
349            .unwrap_or_else(|| panic!("request metadata was not added to the request"));
350
351        let headers = http_headers_to_vec(&value)?;
352
353        // Since Bytes shares data, clone does not copy the body.
354        let body = HttpMockBytes::from(value.body().clone());
355
356        Ok(HttpMockRequest::new(
357            metadata.scheme.to_string(),
358            value.uri().to_string(),
359            value.method().to_string(),
360            headers,
361            format!("{:?}", value.version()),
362            body,
363        ))
364    }
365}
366
367/// A general abstraction of an HTTP response for all handlers.
368#[derive(Serialize, Deserialize, Clone)]
369pub struct MockServerHttpResponse {
370    pub status: Option<u16>,
371    pub headers: Option<Vec<(String, String)>>,
372    #[serde(default, with = "opt_vector_serde_base64")]
373    pub body: Option<HttpMockBytes>,
374    pub delay: Option<u64>,
375}
376
377impl MockServerHttpResponse {
378    pub fn new() -> Self {
379        Self {
380            status: None,
381            headers: None,
382            body: None,
383            delay: None,
384        }
385    }
386}
387
388impl Default for MockServerHttpResponse {
389    fn default() -> Self {
390        Self::new()
391    }
392}
393
394impl TryFrom<&http::Response<Bytes>> for MockServerHttpResponse {
395    type Error = Error;
396
397    fn try_from(value: &http::Response<Bytes>) -> Result<Self, Self::Error> {
398        let mut headers = Vec::with_capacity(value.headers().len());
399
400        for (key, value) in value.headers() {
401            let value = value
402                .to_str()
403                .map_err(|err| HeaderDeserializationError(err.to_string()))?;
404
405            headers.push((key.as_str().to_string(), value.to_string()))
406        }
407
408        Ok(Self {
409            status: Some(value.status().as_u16()),
410            headers: if !headers.is_empty() {
411                Some(headers)
412            } else {
413                None
414            },
415            body: if !value.body().is_empty() {
416                Some(HttpMockBytes::from(value.body().clone()))
417            } else {
418                None
419            },
420            delay: None,
421        })
422    }
423}
424
425/// Serializes and deserializes the response body to/from a Base64 string.
426mod opt_vector_serde_base64 {
427    use crate::common::util::HttpMockBytes;
428    use bytes::Bytes;
429    use serde::{Deserialize, Deserializer, Serializer};
430
431    // See the following references:
432    // https://github.com/serde-rs/serde/blob/master/serde/src/ser/impls.rs#L99
433    // https://github.com/serde-rs/serde/issues/661
434    pub fn serialize<T, S>(bytes: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
435    where
436        T: AsRef<[u8]>,
437        S: Serializer,
438    {
439        match bytes {
440            Some(ref value) => serializer.serialize_bytes(base64::encode(value).as_bytes()),
441            None => serializer.serialize_none(),
442        }
443    }
444
445    // See the following references:
446    // https://github.com/serde-rs/serde/issues/1444
447    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<HttpMockBytes>, D::Error>
448    where
449        D: Deserializer<'de>,
450    {
451        #[derive(Deserialize)]
452        struct Wrapper(#[serde(deserialize_with = "from_base64")] HttpMockBytes);
453
454        let v = Option::deserialize(deserializer)?;
455        Ok(v.map(|Wrapper(a)| a))
456    }
457
458    fn from_base64<'de, D>(deserializer: D) -> Result<HttpMockBytes, D::Error>
459    where
460        D: Deserializer<'de>,
461    {
462        let value = Vec::deserialize(deserializer)?;
463        let decoded = base64::decode(value).map_err(serde::de::Error::custom)?;
464        Ok(HttpMockBytes::from(Bytes::from(decoded)))
465    }
466}
467
468/// Prints the response body as UTF8 string
469impl fmt::Debug for MockServerHttpResponse {
470    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471        f.debug_struct("MockServerHttpResponse")
472            .field("status", &self.status)
473            .field("headers", &self.headers)
474            .field(
475                "body",
476                &self
477                    .body
478                    .as_ref()
479                    .map(|x| String::from_utf8_lossy(x.as_ref()).to_string()),
480            )
481            .field("delay", &self.delay)
482            .finish()
483    }
484}
485
486/// A general abstraction of an HTTP request for all handlers.
487#[derive(Serialize, Deserialize, Clone, Debug)]
488pub struct HttpMockRegex(#[serde(with = "serde_regex")] pub regex::Regex);
489
490impl Ord for HttpMockRegex {
491    fn cmp(&self, other: &Self) -> Ordering {
492        self.0.as_str().cmp(other.0.as_str())
493    }
494}
495
496impl PartialOrd for HttpMockRegex {
497    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
498        Some(self.cmp(other))
499    }
500}
501
502impl PartialEq for HttpMockRegex {
503    fn eq(&self, other: &Self) -> bool {
504        self.0.as_str() == other.0.as_str()
505    }
506}
507
508impl Eq for HttpMockRegex {}
509
510impl From<regex::Regex> for HttpMockRegex {
511    fn from(value: regex::Regex) -> Self {
512        HttpMockRegex(value)
513    }
514}
515
516impl From<&str> for HttpMockRegex {
517    fn from(value: &str) -> Self {
518        let re = regex::Regex::from_str(value).expect("cannot parse value as regex");
519        HttpMockRegex::from(re)
520    }
521}
522
523impl From<String> for HttpMockRegex {
524    fn from(value: String) -> Self {
525        HttpMockRegex::from(value.as_str())
526    }
527}
528
529impl fmt::Display for HttpMockRegex {
530    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531        write!(f, "{}", self.0)
532    }
533}
534
535/// A general abstraction of an HTTP request for all handlers.
536#[derive(Serialize, Deserialize, Clone)]
537pub struct RequestRequirements {
538    pub scheme: Option<String>,
539    pub scheme_not: Option<String>, // NEW
540    pub host: Option<String>,
541    pub host_not: Option<Vec<String>>,        // NEW
542    pub host_contains: Option<Vec<String>>,   // NEW
543    pub host_excludes: Option<Vec<String>>,   // NEW
544    pub host_prefix: Option<Vec<String>>,     // NEW
545    pub host_suffix: Option<Vec<String>>,     // NEW
546    pub host_prefix_not: Option<Vec<String>>, // NEW
547    pub host_suffix_not: Option<Vec<String>>, // NEW
548    pub host_matches: Option<Vec<HttpMockRegex>>,
549    pub port: Option<u16>,
550    pub port_not: Option<Vec<u16>>, // NEW
551    pub method: Option<String>,
552    pub method_not: Option<Vec<String>>, // NEW
553    pub path: Option<String>,
554    pub path_not: Option<Vec<String>>,        // NEW
555    pub path_includes: Option<Vec<String>>,   // NEW
556    pub path_excludes: Option<Vec<String>>,   // NEW
557    pub path_prefix: Option<Vec<String>>,     // NEW
558    pub path_suffix: Option<Vec<String>>,     // NEW
559    pub path_prefix_not: Option<Vec<String>>, // NEW
560    pub path_suffix_not: Option<Vec<String>>, // NEW
561    pub path_matches: Option<Vec<HttpMockRegex>>,
562    pub query_param: Option<Vec<(String, String)>>,
563    pub query_param_not: Option<Vec<(String, String)>>, // NEW
564    pub query_param_exists: Option<Vec<String>>,
565    pub query_param_missing: Option<Vec<String>>, // NEW
566    pub query_param_includes: Option<Vec<(String, String)>>, // NEW
567    pub query_param_excludes: Option<Vec<(String, String)>>, // NEW
568    pub query_param_prefix: Option<Vec<(String, String)>>, // NEW
569    pub query_param_suffix: Option<Vec<(String, String)>>, // NEW
570    pub query_param_prefix_not: Option<Vec<(String, String)>>, // NEW
571    pub query_param_suffix_not: Option<Vec<(String, String)>>, // NEW
572    pub query_param_matches: Option<Vec<(HttpMockRegex, HttpMockRegex)>>, // NEW
573    pub query_param_count: Option<Vec<(HttpMockRegex, HttpMockRegex, usize)>>, // NEW
574    pub header: Option<Vec<(String, String)>>,    // CHANGED from headers to header
575    pub header_not: Option<Vec<(String, String)>>, // NEW
576    pub header_exists: Option<Vec<String>>,
577    pub header_missing: Option<Vec<String>>,            // NEW
578    pub header_includes: Option<Vec<(String, String)>>, // NEW
579    pub header_excludes: Option<Vec<(String, String)>>, // NEW
580    pub header_prefix: Option<Vec<(String, String)>>,   // NEW
581    pub header_suffix: Option<Vec<(String, String)>>,   // NEW
582    pub header_prefix_not: Option<Vec<(String, String)>>, // NEW
583    pub header_suffix_not: Option<Vec<(String, String)>>, // NEW
584    pub header_matches: Option<Vec<(HttpMockRegex, HttpMockRegex)>>, // NEW
585    pub header_count: Option<Vec<(HttpMockRegex, HttpMockRegex, usize)>>, // NEW
586    pub cookie: Option<Vec<(String, String)>>,          // CHANGED from cookies to cookie
587    pub cookie_not: Option<Vec<(String, String)>>,      // NEW
588    pub cookie_exists: Option<Vec<String>>,
589    pub cookie_missing: Option<Vec<String>>,            // NEW
590    pub cookie_includes: Option<Vec<(String, String)>>, // NEW
591    pub cookie_excludes: Option<Vec<(String, String)>>, // NEW
592    pub cookie_prefix: Option<Vec<(String, String)>>,   // NEW
593    pub cookie_suffix: Option<Vec<(String, String)>>,   // NEW
594    pub cookie_prefix_not: Option<Vec<(String, String)>>, // NEW
595    pub cookie_suffix_not: Option<Vec<(String, String)>>, // NEW
596    pub cookie_matches: Option<Vec<(HttpMockRegex, HttpMockRegex)>>, // NEW
597    pub cookie_count: Option<Vec<(HttpMockRegex, HttpMockRegex, usize)>>, // NEW          // NEW
598    pub body: Option<HttpMockBytes>,
599    pub body_not: Option<Vec<HttpMockBytes>>,        // NEW
600    pub body_includes: Option<Vec<HttpMockBytes>>,   // CHANG
601    pub body_excludes: Option<Vec<HttpMockBytes>>,   // NEW
602    pub body_prefix: Option<Vec<HttpMockBytes>>,     // NEW
603    pub body_suffix: Option<Vec<HttpMockBytes>>,     // NEW
604    pub body_prefix_not: Option<Vec<HttpMockBytes>>, //
605    pub body_suffix_not: Option<Vec<HttpMockBytes>>, //
606    pub body_matches: Option<Vec<HttpMockRegex>>,    // NEW
607    pub json_body: Option<Value>,
608    pub json_body_not: Option<Value>, // NEW
609    pub json_body_includes: Option<Vec<Value>>,
610    pub json_body_excludes: Option<Vec<Value>>, // NEW
611    pub form_urlencoded_tuple: Option<Vec<(String, String)>>,
612    pub form_urlencoded_tuple_not: Option<Vec<(String, String)>>, // NEW
613    pub form_urlencoded_tuple_exists: Option<Vec<String>>,
614    pub form_urlencoded_tuple_missing: Option<Vec<String>>, // NEW
615    pub form_urlencoded_tuple_includes: Option<Vec<(String, String)>>, // NEW
616    pub form_urlencoded_tuple_excludes: Option<Vec<(String, String)>>, // NEW
617    pub form_urlencoded_tuple_prefix: Option<Vec<(String, String)>>, // NEW
618    pub form_urlencoded_tuple_suffix: Option<Vec<(String, String)>>, // NEW
619    pub form_urlencoded_tuple_prefix_not: Option<Vec<(String, String)>>, // NEW
620    pub form_urlencoded_tuple_suffix_not: Option<Vec<(String, String)>>, // NEW
621    pub form_urlencoded_tuple_matches: Option<Vec<(HttpMockRegex, HttpMockRegex)>>, // NEW
622    pub form_urlencoded_tuple_count: Option<Vec<(HttpMockRegex, HttpMockRegex, usize)>>, // NEW
623    #[serde(skip)]
624    pub is_true: Option<Vec<Arc<dyn Fn(&HttpMockRequest) -> bool + Sync + Send>>>, // NEW + DEPRECATE matches() -> point to using "is_true" instead
625    #[serde(skip)]
626    pub is_false: Option<Vec<Arc<dyn Fn(&HttpMockRequest) -> bool + Sync + Send>>>, // NEW
627}
628
629impl Default for RequestRequirements {
630    fn default() -> Self {
631        Self::new()
632    }
633}
634
635impl RequestRequirements {
636    pub fn new() -> Self {
637        Self {
638            scheme: None,
639            scheme_not: None,
640            host: None,
641            host_not: None,
642            host_contains: None,
643            host_excludes: None,
644            host_prefix: None,
645            host_suffix: None,
646            host_prefix_not: None,
647            host_suffix_not: None,
648            host_matches: None,
649            port: None,
650            path: None,
651            path_not: None,
652            path_includes: None,
653            path_excludes: None,
654            path_prefix: None,
655            path_suffix: None,
656            path_prefix_not: None,
657            path_suffix_not: None,
658            path_matches: None,
659            method: None,
660            header: None,
661            header_not: None,
662            header_exists: None,
663            header_missing: None,
664            header_includes: None,
665            header_excludes: None,
666            header_prefix: None,
667            header_suffix: None,
668            header_prefix_not: None,
669            header_suffix_not: None,
670            header_matches: None,
671            header_count: None,
672            cookie: None,
673            cookie_not: None,
674            cookie_exists: None,
675            cookie_missing: None,
676            cookie_includes: None,
677            cookie_excludes: None,
678            cookie_prefix: None,
679            cookie_suffix: None,
680            cookie_prefix_not: None,
681            cookie_suffix_not: None,
682            cookie_matches: None,
683            cookie_count: None,
684            body: None,
685            json_body: None,
686            json_body_not: None,
687            json_body_includes: None,
688            body_includes: None,
689            body_excludes: None,
690            body_prefix: None,
691            body_suffix: None,
692            body_prefix_not: None,
693            body_suffix_not: None,
694            body_matches: None,
695            query_param_exists: None,
696            query_param_missing: None,
697            query_param_includes: None,
698            query_param_excludes: None,
699            query_param_prefix: None,
700            query_param_suffix: None,
701            query_param_prefix_not: None,
702            query_param_suffix_not: None,
703            query_param_matches: None,
704            query_param_count: None,
705            query_param: None,
706            form_urlencoded_tuple: None,
707            form_urlencoded_tuple_not: None,
708            form_urlencoded_tuple_exists: None,
709            form_urlencoded_tuple_missing: None,
710            form_urlencoded_tuple_includes: None,
711            form_urlencoded_tuple_excludes: None,
712            form_urlencoded_tuple_prefix: None,
713            form_urlencoded_tuple_suffix: None,
714            form_urlencoded_tuple_prefix_not: None,
715            form_urlencoded_tuple_suffix_not: None,
716            form_urlencoded_tuple_matches: None,
717            form_urlencoded_tuple_count: None,
718            is_true: None,
719            port_not: None,
720            method_not: None,
721            query_param_not: None,
722            body_not: None,
723            json_body_excludes: None,
724            is_false: None,
725        }
726    }
727}
728
729/// A Request that is made to set a new mock.
730#[derive(Serialize, Deserialize, Clone)]
731pub struct MockDefinition {
732    pub request: RequestRequirements,
733    pub response: MockServerHttpResponse,
734}
735
736impl MockDefinition {
737    pub fn new(req: RequestRequirements, mock: MockServerHttpResponse) -> Self {
738        Self {
739            request: req,
740            response: mock,
741        }
742    }
743}
744
745#[derive(Serialize, Deserialize, Clone)]
746pub struct ActiveMock {
747    pub id: usize,
748    pub call_counter: usize,
749    pub definition: MockDefinition,
750    pub is_static: bool,
751}
752
753impl ActiveMock {
754    pub fn new(
755        id: usize,
756        definition: MockDefinition,
757        call_counter: usize,
758        is_static: bool,
759    ) -> Self {
760        ActiveMock {
761            id,
762            definition,
763            call_counter,
764            is_static,
765        }
766    }
767}
768
769#[derive(Serialize, Deserialize, Clone)]
770pub struct ActiveForwardingRule {
771    pub id: usize,
772    pub config: ForwardingRuleConfig,
773}
774
775impl ActiveForwardingRule {
776    pub fn new(id: usize, config: ForwardingRuleConfig) -> Self {
777        ActiveForwardingRule { id, config }
778    }
779}
780
781#[derive(Serialize, Deserialize, Clone)]
782pub struct ActiveProxyRule {
783    pub id: usize,
784    pub config: ProxyRuleConfig,
785}
786
787impl ActiveProxyRule {
788    pub fn new(id: usize, config: ProxyRuleConfig) -> Self {
789        ActiveProxyRule { id, config }
790    }
791}
792
793#[derive(Serialize, Deserialize, Clone)]
794pub struct ActiveRecording {
795    pub id: usize,
796    pub config: RecordingRuleConfig,
797    pub mocks: Vec<MockDefinition>,
798}
799
800impl ActiveRecording {
801    pub fn new(id: usize, config: RecordingRuleConfig) -> Self {
802        ActiveRecording {
803            id,
804            config,
805            mocks: vec![],
806        }
807    }
808}
809
810#[derive(Serialize, Deserialize)]
811pub struct ClosestMatch {
812    pub request: HttpMockRequest,
813    pub request_index: usize,
814    pub mismatches: Vec<Mismatch>,
815}
816
817#[derive(Serialize, Deserialize)]
818pub struct ErrorResponse {
819    pub message: String,
820}
821
822impl ErrorResponse {
823    pub fn new<T>(message: &T) -> ErrorResponse
824    where
825        T: ToString,
826    {
827        ErrorResponse {
828            message: message.to_string(),
829        }
830    }
831}
832
833// *************************************************************************************************
834// Diff and Change correspond to difference::Changeset and Difference structs. They are duplicated
835// here only for the reason to make them serializable/deserializable using serde.
836// *************************************************************************************************
837#[derive(PartialEq, Debug, Serialize, Deserialize)]
838pub enum Diff {
839    Same(String),
840    Add(String),
841    Rem(String),
842}
843
844#[derive(Debug, Serialize, Deserialize)]
845pub struct DiffResult {
846    pub differences: Vec<Diff>,
847    pub distance: f32,
848    pub tokenizer: Tokenizer,
849}
850
851#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Copy)]
852pub enum Tokenizer {
853    Line,
854    Word,
855    Character,
856}
857
858#[derive(Debug, Serialize, Deserialize)]
859pub struct KeyValueComparisonKeyValuePair {
860    pub key: String,
861    pub value: Option<String>,
862}
863
864#[derive(Debug, Serialize, Deserialize)]
865pub struct KeyValueComparisonAttribute {
866    pub operator: String,
867    pub expected: String,
868    pub actual: Option<String>,
869}
870
871#[derive(Debug, Serialize, Deserialize)]
872pub struct KeyValueComparison {
873    pub key: Option<KeyValueComparisonAttribute>,
874    pub value: Option<KeyValueComparisonAttribute>,
875    pub expected_count: Option<usize>,
876    pub actual_count: Option<usize>,
877    pub all: Vec<KeyValueComparisonKeyValuePair>,
878}
879
880#[derive(Debug, Serialize, Deserialize)]
881pub struct FunctionComparison {
882    pub index: usize,
883}
884
885#[derive(Debug, Serialize, Deserialize)]
886pub struct SingleValueComparison {
887    pub operator: String,
888    pub expected: String,
889    pub actual: String,
890}
891
892#[derive(Debug, Serialize, Deserialize)]
893pub struct Mismatch {
894    pub entity: String,
895    pub matcher_method: String,
896    pub comparison: Option<SingleValueComparison>,
897    pub key_value_comparison: Option<KeyValueComparison>,
898    pub function_comparison: Option<FunctionComparison>,
899    pub matching_strategy: Option<MatchingStrategy>,
900    pub best_match: bool,
901    pub diff: Option<DiffResult>,
902}
903
904// *************************************************************************************************
905// Configs and Builders
906// *************************************************************************************************
907
908#[derive(Serialize, Deserialize, Clone, Default)]
909pub struct RecordingRuleConfig {
910    pub request_requirements: RequestRequirements,
911    pub record_headers: Vec<String>,
912    pub record_response_delays: bool,
913}
914
915#[derive(Serialize, Deserialize, Clone, Default)]
916pub struct ProxyRuleConfig {
917    pub request_requirements: RequestRequirements,
918    pub request_header: Vec<(String, String)>,
919}
920
921#[derive(Serialize, Deserialize, Clone, Default)]
922pub struct ForwardingRuleConfig {
923    pub target_base_url: String,
924    pub request_requirements: RequestRequirements,
925    pub request_header: Vec<(String, String)>,
926}
927
928#[derive(Debug, PartialEq, Serialize, Deserialize)]
929pub struct NameValueStringPair {
930    name: String,
931    value: String,
932}
933
934#[derive(Debug, PartialEq, Serialize, Deserialize)]
935pub struct NameValuePatternPair {
936    name: HttpMockRegex,
937    value: HttpMockRegex,
938}
939
940#[derive(Debug, PartialEq, Serialize, Deserialize)]
941pub struct KeyPatternCountPair {
942    key: HttpMockRegex,
943    count: usize,
944}
945
946#[derive(Debug, PartialEq, Serialize, Deserialize)]
947pub struct ValuePatternCountPair {
948    value: HttpMockRegex,
949    count: usize,
950}
951
952#[derive(Debug, PartialEq, Serialize, Deserialize)]
953pub struct KeyValuePatternCountTriple {
954    name: HttpMockRegex,
955    value: HttpMockRegex,
956    count: usize,
957}
958
959#[derive(Debug, Serialize, Deserialize)]
960pub struct StaticRequestRequirements {
961    // Scheme-related fields
962    #[serde(skip_serializing_if = "Option::is_none")]
963    pub scheme: Option<String>,
964    #[serde(skip_serializing_if = "Option::is_none")]
965    pub scheme_not: Option<String>,
966
967    // Host-related fields
968    #[serde(skip_serializing_if = "Option::is_none")]
969    pub host: Option<String>,
970    #[serde(skip_serializing_if = "Option::is_none")]
971    pub host_not: Option<Vec<String>>,
972    #[serde(skip_serializing_if = "Option::is_none")]
973    pub host_contains: Option<Vec<String>>,
974    #[serde(skip_serializing_if = "Option::is_none")]
975    pub host_excludes: Option<Vec<String>>,
976    #[serde(skip_serializing_if = "Option::is_none")]
977    pub host_prefix: Option<Vec<String>>,
978    #[serde(skip_serializing_if = "Option::is_none")]
979    pub host_suffix: Option<Vec<String>>,
980    #[serde(skip_serializing_if = "Option::is_none")]
981    pub host_prefix_not: Option<Vec<String>>,
982    #[serde(skip_serializing_if = "Option::is_none")]
983    pub host_suffix_not: Option<Vec<String>>,
984    #[serde(skip_serializing_if = "Option::is_none")]
985    pub host_matches: Option<Vec<HttpMockRegex>>,
986
987    // Port-related fields
988    #[serde(skip_serializing_if = "Option::is_none")]
989    pub port: Option<u16>,
990    #[serde(skip_serializing_if = "Option::is_none")]
991    pub port_not: Option<Vec<u16>>,
992
993    // Path-related fields
994    #[serde(skip_serializing_if = "Option::is_none")]
995    pub path: Option<String>,
996    #[serde(skip_serializing_if = "Option::is_none")]
997    pub path_not: Option<Vec<String>>,
998    #[serde(skip_serializing_if = "Option::is_none")]
999    pub path_contains: Option<Vec<String>>,
1000    #[serde(skip_serializing_if = "Option::is_none")]
1001    pub path_excludes: Option<Vec<String>>,
1002    #[serde(skip_serializing_if = "Option::is_none")]
1003    pub path_prefix: Option<Vec<String>>,
1004    #[serde(skip_serializing_if = "Option::is_none")]
1005    pub path_suffix: Option<Vec<String>>,
1006    #[serde(skip_serializing_if = "Option::is_none")]
1007    pub path_prefix_not: Option<Vec<String>>,
1008    #[serde(skip_serializing_if = "Option::is_none")]
1009    pub path_suffix_not: Option<Vec<String>>,
1010    #[serde(skip_serializing_if = "Option::is_none")]
1011    pub path_matches: Option<Vec<HttpMockRegex>>,
1012
1013    // Method-related fields
1014    #[serde(skip_serializing_if = "Option::is_none")]
1015    pub method: Option<Method>,
1016    #[serde(skip_serializing_if = "Option::is_none")]
1017    pub method_not: Option<Vec<Method>>,
1018
1019    // Query Parameter-related fields
1020    #[serde(skip_serializing_if = "Option::is_none")]
1021    pub query_param: Option<Vec<NameValueStringPair>>,
1022    #[serde(skip_serializing_if = "Option::is_none")]
1023    pub query_param_not: Option<Vec<NameValueStringPair>>,
1024    #[serde(skip_serializing_if = "Option::is_none")]
1025    pub query_param_exists: Option<Vec<String>>,
1026    #[serde(skip_serializing_if = "Option::is_none")]
1027    pub query_param_missing: Option<Vec<String>>,
1028    #[serde(skip_serializing_if = "Option::is_none")]
1029    pub query_param_contains: Option<Vec<NameValueStringPair>>,
1030    #[serde(skip_serializing_if = "Option::is_none")]
1031    pub query_param_excludes: Option<Vec<NameValueStringPair>>,
1032    #[serde(skip_serializing_if = "Option::is_none")]
1033    pub query_param_prefix: Option<Vec<NameValueStringPair>>,
1034    #[serde(skip_serializing_if = "Option::is_none")]
1035    pub query_param_suffix: Option<Vec<NameValueStringPair>>,
1036    #[serde(skip_serializing_if = "Option::is_none")]
1037    pub query_param_prefix_not: Option<Vec<NameValueStringPair>>,
1038    #[serde(skip_serializing_if = "Option::is_none")]
1039    pub query_param_suffix_not: Option<Vec<NameValueStringPair>>,
1040    #[serde(skip_serializing_if = "Option::is_none")]
1041    pub query_param_matches: Option<Vec<NameValuePatternPair>>,
1042    #[serde(skip_serializing_if = "Option::is_none")]
1043    pub query_param_count: Option<Vec<KeyValuePatternCountTriple>>,
1044
1045    // Header-related fields
1046    #[serde(skip_serializing_if = "Option::is_none")]
1047    pub header: Option<Vec<NameValueStringPair>>,
1048    #[serde(skip_serializing_if = "Option::is_none")]
1049    pub header_not: Option<Vec<NameValueStringPair>>,
1050    #[serde(skip_serializing_if = "Option::is_none")]
1051    pub header_exists: Option<Vec<String>>,
1052    #[serde(skip_serializing_if = "Option::is_none")]
1053    pub header_missing: Option<Vec<String>>,
1054    #[serde(skip_serializing_if = "Option::is_none")]
1055    pub header_contains: Option<Vec<NameValueStringPair>>,
1056    #[serde(skip_serializing_if = "Option::is_none")]
1057    pub header_excludes: Option<Vec<NameValueStringPair>>,
1058    #[serde(skip_serializing_if = "Option::is_none")]
1059    pub header_prefix: Option<Vec<NameValueStringPair>>,
1060    #[serde(skip_serializing_if = "Option::is_none")]
1061    pub header_suffix: Option<Vec<NameValueStringPair>>,
1062    #[serde(skip_serializing_if = "Option::is_none")]
1063    pub header_prefix_not: Option<Vec<NameValueStringPair>>,
1064    #[serde(skip_serializing_if = "Option::is_none")]
1065    pub header_suffix_not: Option<Vec<NameValueStringPair>>,
1066    #[serde(skip_serializing_if = "Option::is_none")]
1067    pub header_matches: Option<Vec<NameValuePatternPair>>,
1068    #[serde(skip_serializing_if = "Option::is_none")]
1069    pub header_count: Option<Vec<KeyValuePatternCountTriple>>,
1070
1071    // Cookie-related fields
1072    #[serde(skip_serializing_if = "Option::is_none")]
1073    pub cookie: Option<Vec<NameValueStringPair>>,
1074    #[serde(skip_serializing_if = "Option::is_none")]
1075    pub cookie_not: Option<Vec<NameValueStringPair>>,
1076    #[serde(skip_serializing_if = "Option::is_none")]
1077    pub cookie_exists: Option<Vec<String>>,
1078    #[serde(skip_serializing_if = "Option::is_none")]
1079    pub cookie_missing: Option<Vec<String>>,
1080    #[serde(skip_serializing_if = "Option::is_none")]
1081    pub cookie_contains: Option<Vec<NameValueStringPair>>,
1082    #[serde(skip_serializing_if = "Option::is_none")]
1083    pub cookie_excludes: Option<Vec<NameValueStringPair>>,
1084    #[serde(skip_serializing_if = "Option::is_none")]
1085    pub cookie_prefix: Option<Vec<NameValueStringPair>>,
1086    #[serde(skip_serializing_if = "Option::is_none")]
1087    pub cookie_suffix: Option<Vec<NameValueStringPair>>,
1088    #[serde(skip_serializing_if = "Option::is_none")]
1089    pub cookie_prefix_not: Option<Vec<NameValueStringPair>>,
1090    #[serde(skip_serializing_if = "Option::is_none")]
1091    pub cookie_suffix_not: Option<Vec<NameValueStringPair>>,
1092    #[serde(skip_serializing_if = "Option::is_none")]
1093    pub cookie_matches: Option<Vec<NameValuePatternPair>>,
1094    #[serde(skip_serializing_if = "Option::is_none")]
1095    pub cookie_count: Option<Vec<KeyValuePatternCountTriple>>,
1096
1097    // Body-related fields
1098    #[serde(skip_serializing_if = "Option::is_none")]
1099    pub body: Option<String>,
1100    #[serde(skip_serializing_if = "Option::is_none")]
1101    pub body_base64: Option<String>,
1102    #[serde(skip_serializing_if = "Option::is_none")]
1103    pub body_not: Option<Vec<String>>,
1104    #[serde(skip_serializing_if = "Option::is_none")]
1105    pub body_not_base64: Option<Vec<String>>,
1106    #[serde(skip_serializing_if = "Option::is_none")]
1107    pub body_contains: Option<Vec<String>>,
1108    #[serde(skip_serializing_if = "Option::is_none")]
1109    pub body_contains_base64: Option<Vec<String>>,
1110    #[serde(skip_serializing_if = "Option::is_none")]
1111    pub body_excludes: Option<Vec<String>>,
1112    #[serde(skip_serializing_if = "Option::is_none")]
1113    pub body_excludes_base64: Option<Vec<String>>,
1114    #[serde(skip_serializing_if = "Option::is_none")]
1115    pub body_prefix: Option<Vec<String>>,
1116    #[serde(skip_serializing_if = "Option::is_none")]
1117    pub body_prefix_base64: Option<Vec<String>>,
1118    #[serde(skip_serializing_if = "Option::is_none")]
1119    pub body_suffix: Option<Vec<String>>,
1120    #[serde(skip_serializing_if = "Option::is_none")]
1121    pub body_suffix_base64: Option<Vec<String>>,
1122    #[serde(skip_serializing_if = "Option::is_none")]
1123    pub body_prefix_not: Option<Vec<String>>,
1124    #[serde(skip_serializing_if = "Option::is_none")]
1125    pub body_prefix_not_base64: Option<Vec<String>>,
1126    #[serde(skip_serializing_if = "Option::is_none")]
1127    pub body_suffix_not: Option<Vec<String>>,
1128    #[serde(skip_serializing_if = "Option::is_none")]
1129    pub body_suffix_not_base64: Option<Vec<String>>,
1130    #[serde(skip_serializing_if = "Option::is_none")]
1131    pub body_matches: Option<Vec<HttpMockRegex>>,
1132
1133    // JSON Body-related fields
1134    #[serde(skip_serializing_if = "Option::is_none")]
1135    pub json_body: Option<Value>,
1136    #[serde(skip_serializing_if = "Option::is_none")]
1137    pub json_body_not: Option<Value>,
1138    #[serde(skip_serializing_if = "Option::is_none")]
1139    pub json_body_includes: Option<Vec<Value>>,
1140    #[serde(skip_serializing_if = "Option::is_none")]
1141    pub json_body_excludes: Option<Vec<Value>>,
1142
1143    // x-www-form-urlencoded fields
1144    #[serde(skip_serializing_if = "Option::is_none")]
1145    pub form_urlencoded_tuple: Option<Vec<NameValueStringPair>>,
1146    #[serde(skip_serializing_if = "Option::is_none")]
1147    pub form_urlencoded_tuple_not: Option<Vec<NameValueStringPair>>,
1148    #[serde(skip_serializing_if = "Option::is_none")]
1149    pub form_urlencoded_key_exists: Option<Vec<String>>,
1150    #[serde(skip_serializing_if = "Option::is_none")]
1151    pub form_urlencoded_key_missing: Option<Vec<String>>,
1152    #[serde(skip_serializing_if = "Option::is_none")]
1153    pub form_urlencoded_contains: Option<Vec<NameValueStringPair>>,
1154    #[serde(skip_serializing_if = "Option::is_none")]
1155    pub form_urlencoded_excludes: Option<Vec<NameValueStringPair>>,
1156    #[serde(skip_serializing_if = "Option::is_none")]
1157    pub form_urlencoded_prefix: Option<Vec<NameValueStringPair>>,
1158    #[serde(skip_serializing_if = "Option::is_none")]
1159    pub form_urlencoded_suffix: Option<Vec<NameValueStringPair>>,
1160    #[serde(skip_serializing_if = "Option::is_none")]
1161    pub form_urlencoded_prefix_not: Option<Vec<NameValueStringPair>>,
1162    #[serde(skip_serializing_if = "Option::is_none")]
1163    pub form_urlencoded_suffix_not: Option<Vec<NameValueStringPair>>,
1164    #[serde(skip_serializing_if = "Option::is_none")]
1165    pub form_urlencoded_matches: Option<Vec<NameValuePatternPair>>,
1166    #[serde(skip_serializing_if = "Option::is_none")]
1167    pub form_urlencoded_count: Option<Vec<KeyValuePatternCountTriple>>,
1168}
1169
1170#[derive(Debug, Serialize, Deserialize)]
1171pub struct StaticHTTPResponse {
1172    #[serde(skip_serializing_if = "Option::is_none")]
1173    pub status: Option<u16>,
1174    #[serde(skip_serializing_if = "Option::is_none")]
1175    pub header: Option<Vec<NameValueStringPair>>,
1176    #[serde(skip_serializing_if = "Option::is_none")]
1177    pub body: Option<String>,
1178    #[serde(skip_serializing_if = "Option::is_none")]
1179    pub body_base64: Option<String>,
1180    #[serde(skip_serializing_if = "Option::is_none")]
1181    pub delay: Option<u64>,
1182}
1183
1184#[derive(Debug, Serialize, Deserialize)]
1185pub struct StaticMockDefinition {
1186    when: StaticRequestRequirements,
1187    then: StaticHTTPResponse,
1188}
1189
1190impl TryInto<MockDefinition> for StaticMockDefinition {
1191    type Error = Error;
1192
1193    fn try_into(self) -> Result<MockDefinition, Self::Error> {
1194        Ok(MockDefinition {
1195            request: RequestRequirements {
1196                // Scheme-related fields
1197                scheme: self.when.scheme,
1198                scheme_not: self.when.scheme_not,
1199
1200                // Host-related fields
1201                host: self.when.host,
1202                host_not: self.when.host_not,
1203                host_contains: self.when.host_contains,
1204                host_excludes: self.when.host_excludes,
1205                host_prefix: self.when.host_prefix,
1206                host_suffix: self.when.host_suffix,
1207                host_prefix_not: self.when.host_prefix_not,
1208                host_suffix_not: self.when.host_suffix_not,
1209                host_matches: self.when.host_matches,
1210
1211                // Port-related fields
1212                port: self.when.port,
1213                port_not: self.when.port_not,
1214
1215                // Path-related fields
1216                path: self.when.path,
1217                path_not: self.when.path_not,
1218                path_includes: self.when.path_contains,
1219                path_excludes: self.when.path_excludes,
1220                path_prefix: self.when.path_prefix,
1221                path_suffix: self.when.path_suffix,
1222                path_prefix_not: self.when.path_prefix_not,
1223                path_suffix_not: self.when.path_suffix_not,
1224                path_matches: self.when.path_matches,
1225
1226                // Method-related fields
1227                method: self.when.method.map(|m| m.to_string()),
1228                method_not: from_method_vec(self.when.method_not),
1229                // Query Parameter-related fields
1230                query_param: from_name_value_string_pair_vec(self.when.query_param),
1231                query_param_not: from_name_value_string_pair_vec(self.when.query_param_not),
1232                query_param_exists: self.when.query_param_exists,
1233                query_param_missing: self.when.query_param_missing,
1234                query_param_includes: from_name_value_string_pair_vec(
1235                    self.when.query_param_contains,
1236                ),
1237                query_param_excludes: from_name_value_string_pair_vec(
1238                    self.when.query_param_excludes,
1239                ),
1240                query_param_prefix: from_name_value_string_pair_vec(self.when.query_param_prefix),
1241                query_param_suffix: from_name_value_string_pair_vec(self.when.query_param_suffix),
1242                query_param_prefix_not: from_name_value_string_pair_vec(
1243                    self.when.query_param_prefix_not,
1244                ),
1245                query_param_suffix_not: from_name_value_string_pair_vec(
1246                    self.when.query_param_suffix_not,
1247                ),
1248                query_param_matches: from_name_value_pattern_pair_vec(
1249                    self.when.query_param_matches,
1250                ),
1251                query_param_count: from_key_value_pattern_count_triple_vec(
1252                    self.when.query_param_count,
1253                ),
1254
1255                // Header-related fields
1256                header: from_name_value_string_pair_vec(self.when.header),
1257                header_not: from_name_value_string_pair_vec(self.when.header_not),
1258                header_exists: self.when.header_exists,
1259                header_missing: self.when.header_missing,
1260                header_includes: from_name_value_string_pair_vec(self.when.header_contains),
1261                header_excludes: from_name_value_string_pair_vec(self.when.header_excludes),
1262                header_prefix: from_name_value_string_pair_vec(self.when.header_prefix),
1263                header_suffix: from_name_value_string_pair_vec(self.when.header_suffix),
1264                header_prefix_not: from_name_value_string_pair_vec(self.when.header_prefix_not),
1265                header_suffix_not: from_name_value_string_pair_vec(self.when.header_suffix_not),
1266                header_matches: from_name_value_pattern_pair_vec(self.when.header_matches),
1267                header_count: from_key_value_pattern_count_triple_vec(self.when.header_count),
1268                // Cookie-related fields
1269                cookie: from_name_value_string_pair_vec(self.when.cookie),
1270                cookie_not: from_name_value_string_pair_vec(self.when.cookie_not),
1271                cookie_exists: self.when.cookie_exists,
1272                cookie_missing: self.when.cookie_missing,
1273                cookie_includes: from_name_value_string_pair_vec(self.when.cookie_contains),
1274                cookie_excludes: from_name_value_string_pair_vec(self.when.cookie_excludes),
1275                cookie_prefix: from_name_value_string_pair_vec(self.when.cookie_prefix),
1276                cookie_suffix: from_name_value_string_pair_vec(self.when.cookie_suffix),
1277                cookie_prefix_not: from_name_value_string_pair_vec(self.when.cookie_prefix_not),
1278                cookie_suffix_not: from_name_value_string_pair_vec(self.when.cookie_suffix_not),
1279                cookie_matches: from_name_value_pattern_pair_vec(self.when.cookie_matches),
1280                cookie_count: from_key_value_pattern_count_triple_vec(self.when.cookie_count),
1281
1282                // Body-related fields
1283                body: from_string_to_bytes_choose(self.when.body, self.when.body_base64),
1284                body_not: to_bytes_vec(self.when.body_not, self.when.body_not_base64),
1285                body_includes: to_bytes_vec(
1286                    self.when.body_contains,
1287                    self.when.body_contains_base64,
1288                ),
1289                body_excludes: to_bytes_vec(
1290                    self.when.body_excludes,
1291                    self.when.body_excludes_base64,
1292                ),
1293                body_prefix: to_bytes_vec(self.when.body_prefix, self.when.body_prefix_base64),
1294                body_suffix: to_bytes_vec(self.when.body_suffix, self.when.body_suffix_base64),
1295                body_prefix_not: to_bytes_vec(
1296                    self.when.body_prefix_not,
1297                    self.when.body_prefix_not_base64,
1298                ),
1299                body_suffix_not: to_bytes_vec(
1300                    self.when.body_suffix_not,
1301                    self.when.body_suffix_not_base64,
1302                ),
1303                body_matches: from_pattern_vec(self.when.body_matches),
1304
1305                // JSON Body-related fields
1306                json_body: self.when.json_body,
1307                json_body_not: self.when.json_body_not,
1308                json_body_includes: self.when.json_body_includes,
1309                json_body_excludes: self.when.json_body_excludes,
1310
1311                // x-www-form-urlencoded fields
1312                form_urlencoded_tuple: from_name_value_string_pair_vec(
1313                    self.when.form_urlencoded_tuple,
1314                ),
1315                form_urlencoded_tuple_not: from_name_value_string_pair_vec(
1316                    self.when.form_urlencoded_tuple_not,
1317                ),
1318                form_urlencoded_tuple_exists: self.when.form_urlencoded_key_exists,
1319                form_urlencoded_tuple_missing: self.when.form_urlencoded_key_missing,
1320                form_urlencoded_tuple_includes: from_name_value_string_pair_vec(
1321                    self.when.form_urlencoded_contains,
1322                ),
1323                form_urlencoded_tuple_excludes: from_name_value_string_pair_vec(
1324                    self.when.form_urlencoded_excludes,
1325                ),
1326                form_urlencoded_tuple_prefix: from_name_value_string_pair_vec(
1327                    self.when.form_urlencoded_prefix,
1328                ),
1329                form_urlencoded_tuple_suffix: from_name_value_string_pair_vec(
1330                    self.when.form_urlencoded_suffix,
1331                ),
1332                form_urlencoded_tuple_prefix_not: from_name_value_string_pair_vec(
1333                    self.when.form_urlencoded_prefix_not,
1334                ),
1335                form_urlencoded_tuple_suffix_not: from_name_value_string_pair_vec(
1336                    self.when.form_urlencoded_suffix_not,
1337                ),
1338                form_urlencoded_tuple_matches: from_name_value_pattern_pair_vec(
1339                    self.when.form_urlencoded_matches,
1340                ),
1341
1342                form_urlencoded_tuple_count: from_key_value_pattern_count_triple_vec(
1343                    self.when.form_urlencoded_count,
1344                ),
1345
1346                // Boolean dynamic checks
1347                is_true: None,
1348                is_false: None,
1349            },
1350            response: MockServerHttpResponse {
1351                status: self.then.status,
1352                headers: from_name_value_string_pair_vec(self.then.header),
1353                body: from_string_to_bytes_choose(self.then.body, self.then.body_base64),
1354                delay: self.then.delay,
1355            },
1356        })
1357    }
1358}
1359
1360fn to_method_vec(vec: Option<Vec<String>>) -> Option<Vec<Method>> {
1361    vec.map(|vec| vec.iter().map(|val| Method::from(val.as_str())).collect())
1362}
1363
1364fn from_method_vec(value: Option<Vec<Method>>) -> Option<Vec<String>> {
1365    value.map(|vec| vec.iter().map(|m| m.to_string()).collect())
1366}
1367
1368fn to_pattern_vec(vec: Option<Vec<String>>) -> Option<Vec<HttpMockRegex>> {
1369    vec.map(|vec| {
1370        vec.iter()
1371            .map(|val| HttpMockRegex(regex::Regex::from_str(val).expect("cannot parse regex")))
1372            .collect()
1373    })
1374}
1375
1376fn from_pattern_vec(patterns: Option<Vec<HttpMockRegex>>) -> Option<Vec<HttpMockRegex>> {
1377    patterns.map(|vec| vec.iter().cloned().collect())
1378}
1379
1380fn from_name_value_string_pair_vec(
1381    kvp: Option<Vec<NameValueStringPair>>,
1382) -> Option<Vec<(String, String)>> {
1383    kvp.map(|vec| vec.into_iter().map(|nvp| (nvp.name, nvp.value)).collect())
1384}
1385
1386fn from_name_value_pattern_pair_vec(
1387    kvp: Option<Vec<NameValuePatternPair>>,
1388) -> Option<Vec<(HttpMockRegex, HttpMockRegex)>> {
1389    kvp.map(|vec| {
1390        vec.into_iter()
1391            .map(|pair| (pair.name, pair.value))
1392            .collect()
1393    })
1394}
1395
1396fn from_string_pair_vec(vec: Option<Vec<(String, String)>>) -> Option<Vec<NameValueStringPair>> {
1397    vec.map(|vec| {
1398        vec.into_iter()
1399            .map(|(name, value)| NameValueStringPair { name, value })
1400            .collect()
1401    })
1402}
1403
1404fn from_key_pattern_count_pair_vec(
1405    input: Option<Vec<KeyPatternCountPair>>,
1406) -> Option<Vec<(HttpMockRegex, usize)>> {
1407    input.map(|vec| vec.into_iter().map(|pair| (pair.key, pair.count)).collect())
1408}
1409
1410fn from_value_pattern_count_pair_vec(
1411    input: Option<Vec<ValuePatternCountPair>>,
1412) -> Option<Vec<(HttpMockRegex, usize)>> {
1413    input.map(|vec| {
1414        vec.into_iter()
1415            .map(|pair| (pair.value, pair.count))
1416            .collect()
1417    })
1418}
1419
1420fn from_key_value_pattern_count_triple_vec(
1421    input: Option<Vec<KeyValuePatternCountTriple>>,
1422) -> Option<Vec<(HttpMockRegex, HttpMockRegex, usize)>> {
1423    input.map(|vec| {
1424        vec.into_iter()
1425            .map(|triple| (triple.name, triple.value, triple.count))
1426            .collect()
1427    })
1428}
1429
1430fn to_name_value_string_pair_vec(
1431    vec: Option<Vec<(String, String)>>,
1432) -> Option<Vec<NameValueStringPair>> {
1433    vec.map(|vec| {
1434        vec.into_iter()
1435            .map(|(name, value)| NameValueStringPair { name, value })
1436            .collect()
1437    })
1438}
1439
1440fn to_name_value_pattern_pair_vec(
1441    vec: Option<Vec<(HttpMockRegex, HttpMockRegex)>>,
1442) -> Option<Vec<NameValuePatternPair>> {
1443    vec.map(|vec| {
1444        vec.into_iter()
1445            .map(|(name, value)| NameValuePatternPair { name, value })
1446            .collect()
1447    })
1448}
1449
1450fn to_key_pattern_count_pair_vec(
1451    vec: Option<Vec<(HttpMockRegex, usize)>>,
1452) -> Option<Vec<KeyPatternCountPair>> {
1453    vec.map(|vec| {
1454        vec.into_iter()
1455            .map(|(key, count)| KeyPatternCountPair { key, count })
1456            .collect()
1457    })
1458}
1459
1460fn to_value_pattern_count_pair_vec(
1461    vec: Option<Vec<(HttpMockRegex, usize)>>,
1462) -> Option<Vec<ValuePatternCountPair>> {
1463    vec.map(|vec| {
1464        vec.into_iter()
1465            .map(|(value, count)| ValuePatternCountPair { value, count })
1466            .collect()
1467    })
1468}
1469
1470fn to_key_value_pattern_count_triple_vec(
1471    vec: Option<Vec<(HttpMockRegex, HttpMockRegex, usize)>>,
1472) -> Option<Vec<KeyValuePatternCountTriple>> {
1473    vec.map(|vec| {
1474        vec.into_iter()
1475            .map(|(name, value, count)| KeyValuePatternCountTriple { name, value, count })
1476            .collect()
1477    })
1478}
1479
1480fn from_bytes_to_string(data: Option<HttpMockBytes>) -> (Option<String>, Option<String>) {
1481    let mut text_representation = None;
1482    let mut base64_representation = None;
1483
1484    if let Some(bytes_container) = data {
1485        if let Ok(text_str) = std::str::from_utf8(&bytes_container.to_bytes()) {
1486            text_representation = Some(text_str.to_string());
1487        } else {
1488            base64_representation = Some(base64::encode(&bytes_container.to_bytes()));
1489        }
1490    }
1491
1492    (text_representation, base64_representation)
1493}
1494
1495fn bytes_to_string_vec(
1496    data: Option<Vec<HttpMockBytes>>,
1497) -> (Option<Vec<String>>, Option<Vec<String>>) {
1498    let mut text_representations = Vec::new();
1499    let mut base64_representations = Vec::new();
1500
1501    if let Some(bytes_vec) = data {
1502        for bytes_container in bytes_vec {
1503            let bytes = bytes_container.to_bytes();
1504            if let Ok(text) = std::str::from_utf8(&bytes) {
1505                text_representations.push(text.to_owned());
1506            } else {
1507                base64_representations.push(base64::encode(&bytes));
1508            }
1509        }
1510    }
1511
1512    let text_opt_vec = if !text_representations.is_empty() {
1513        Some(text_representations)
1514    } else {
1515        None
1516    };
1517
1518    let base64_opt_vec = if !base64_representations.is_empty() {
1519        Some(base64_representations)
1520    } else {
1521        None
1522    };
1523
1524    (text_opt_vec, base64_opt_vec)
1525}
1526
1527fn to_bytes_vec(
1528    option_string: Option<Vec<String>>,
1529    option_base64: Option<Vec<String>>,
1530) -> Option<Vec<HttpMockBytes>> {
1531    let mut result = Vec::new();
1532
1533    if let Some(strings) = option_string {
1534        result.extend(
1535            strings
1536                .into_iter()
1537                .map(|s| HttpMockBytes::from(Bytes::from(s))),
1538        );
1539    }
1540
1541    if let Some(base64_strings) = option_base64 {
1542        result.extend(base64_strings.into_iter().filter_map(|s| {
1543            base64::decode(&s)
1544                .ok()
1545                .map(|decoded_bytes| HttpMockBytes::from(Bytes::from(decoded_bytes)))
1546        }));
1547    }
1548
1549    if result.is_empty() {
1550        None
1551    } else {
1552        Some(result)
1553    }
1554}
1555
1556fn to_bytes(option_string: Option<String>, option_base64: Option<String>) -> Option<String> {
1557    if option_string.is_some() {
1558        return option_string;
1559    }
1560
1561    return option_base64;
1562}
1563
1564fn from_string_to_bytes_choose(
1565    option_string: Option<String>,
1566    option_base64: Option<String>,
1567) -> Option<HttpMockBytes> {
1568    let request_body = match (option_string, option_base64) {
1569        (Some(body), None) => Some(body.into_bytes()),
1570        (None, Some(base64_body)) => base64::decode(base64_body).ok(),
1571        _ => None, // Handle unexpected combinations or both None
1572    };
1573
1574    return request_body.map(|s| HttpMockBytes::from(Bytes::from(s)));
1575}
1576
1577impl TryFrom<&MockDefinition> for StaticMockDefinition {
1578    type Error = Error;
1579
1580    fn try_from(value: &MockDefinition) -> Result<Self, Self::Error> {
1581        let value = value.clone();
1582
1583        let (response_body, response_body_base64) = from_bytes_to_string(value.response.body);
1584
1585        let (request_body, request_body_base64) = from_bytes_to_string(value.request.body);
1586        let (request_body_not, request_body_not_base64) =
1587            bytes_to_string_vec(value.request.body_not);
1588        let (request_body_includes, request_body_includes_base64) =
1589            bytes_to_string_vec(value.request.body_includes);
1590        let (request_body_excludes, request_body_excludes_base64) =
1591            bytes_to_string_vec(value.request.body_excludes);
1592        let (request_body_prefix, request_body_prefix_base64) =
1593            bytes_to_string_vec(value.request.body_prefix);
1594        let (request_body_suffix, request_body_suffix_base64) =
1595            bytes_to_string_vec(value.request.body_suffix);
1596        let (request_body_prefix_not, request_body_prefix_not_base64) =
1597            bytes_to_string_vec(value.request.body_prefix_not);
1598        let (request_body_suffix_not, request_body_suffix_not_base64) =
1599            bytes_to_string_vec(value.request.body_suffix_not);
1600
1601        let mut method = None;
1602        if let Some(method_str) = value.request.method {
1603            method = Some(
1604                Method::from_str(&method_str)
1605                    .map_err(|err| StaticMockConversionError(err.to_string()))?,
1606            );
1607        }
1608
1609        Ok(StaticMockDefinition {
1610            when: StaticRequestRequirements {
1611                // Scheme-related fields
1612                scheme: value.request.scheme,
1613                scheme_not: value.request.scheme_not,
1614
1615                // Method-related fields
1616                method,
1617                method_not: to_method_vec(value.request.method_not),
1618                // Host-related fields
1619                host: value.request.host,
1620                host_not: value.request.host_not,
1621                host_contains: value.request.host_contains,
1622                host_excludes: value.request.host_excludes,
1623                host_prefix: value.request.host_prefix,
1624                host_suffix: value.request.host_suffix,
1625                host_prefix_not: value.request.host_prefix_not,
1626                host_suffix_not: value.request.host_suffix_not,
1627                host_matches: value.request.host_matches,
1628
1629                // Port-related fields
1630                port: value.request.port,
1631                port_not: value.request.port_not,
1632
1633                // Path-related fields
1634                path: value.request.path,
1635                path_not: value.request.path_not,
1636                path_contains: value.request.path_includes,
1637                path_excludes: value.request.path_excludes,
1638                path_prefix: value.request.path_prefix,
1639                path_suffix: value.request.path_suffix,
1640                path_prefix_not: value.request.path_prefix_not,
1641                path_suffix_not: value.request.path_suffix_not,
1642                path_matches: from_pattern_vec(value.request.path_matches),
1643
1644                // Header-related fields
1645                header: from_string_pair_vec(value.request.header),
1646                header_not: from_string_pair_vec(value.request.header_not),
1647                header_exists: value.request.header_exists,
1648                header_missing: value.request.header_missing,
1649                header_contains: to_name_value_string_pair_vec(value.request.header_includes),
1650                header_excludes: to_name_value_string_pair_vec(value.request.header_excludes),
1651                header_prefix: to_name_value_string_pair_vec(value.request.header_prefix),
1652                header_suffix: to_name_value_string_pair_vec(value.request.header_suffix),
1653                header_prefix_not: to_name_value_string_pair_vec(value.request.header_prefix_not),
1654                header_suffix_not: to_name_value_string_pair_vec(value.request.header_suffix_not),
1655                header_matches: to_name_value_pattern_pair_vec(value.request.header_matches),
1656                header_count: to_key_value_pattern_count_triple_vec(value.request.header_count),
1657
1658                // Cookie-related fields
1659                cookie: from_string_pair_vec(value.request.cookie),
1660                cookie_not: from_string_pair_vec(value.request.cookie_not),
1661                cookie_exists: value.request.cookie_exists,
1662                cookie_missing: value.request.cookie_missing,
1663                cookie_contains: to_name_value_string_pair_vec(value.request.cookie_includes),
1664                cookie_excludes: to_name_value_string_pair_vec(value.request.cookie_excludes),
1665                cookie_prefix: to_name_value_string_pair_vec(value.request.cookie_prefix),
1666                cookie_suffix: to_name_value_string_pair_vec(value.request.cookie_suffix),
1667                cookie_prefix_not: to_name_value_string_pair_vec(value.request.cookie_prefix_not),
1668                cookie_suffix_not: to_name_value_string_pair_vec(value.request.cookie_suffix_not),
1669                cookie_matches: to_name_value_pattern_pair_vec(value.request.cookie_matches),
1670
1671                cookie_count: to_key_value_pattern_count_triple_vec(value.request.cookie_count),
1672
1673                // Query Parameter-related fields
1674                query_param: from_string_pair_vec(value.request.query_param),
1675                query_param_not: from_string_pair_vec(value.request.query_param_not),
1676                query_param_exists: value.request.query_param_exists,
1677                query_param_missing: value.request.query_param_missing,
1678                query_param_contains: to_name_value_string_pair_vec(
1679                    value.request.query_param_includes,
1680                ),
1681                query_param_excludes: to_name_value_string_pair_vec(
1682                    value.request.query_param_excludes,
1683                ),
1684                query_param_prefix: to_name_value_string_pair_vec(value.request.query_param_prefix),
1685                query_param_suffix: to_name_value_string_pair_vec(value.request.query_param_suffix),
1686                query_param_prefix_not: to_name_value_string_pair_vec(
1687                    value.request.query_param_prefix_not,
1688                ),
1689                query_param_suffix_not: to_name_value_string_pair_vec(
1690                    value.request.query_param_suffix_not,
1691                ),
1692                query_param_matches: to_name_value_pattern_pair_vec(
1693                    value.request.query_param_matches,
1694                ),
1695                query_param_count: to_key_value_pattern_count_triple_vec(
1696                    value.request.query_param_count,
1697                ),
1698
1699                // Body-related fields
1700                body: request_body,
1701                body_base64: request_body_base64,
1702                body_not: request_body_not,
1703                body_not_base64: request_body_not_base64,
1704                body_contains: request_body_includes,
1705                body_contains_base64: request_body_includes_base64,
1706                body_excludes: request_body_excludes,
1707                body_excludes_base64: request_body_excludes_base64,
1708                body_prefix: request_body_prefix,
1709                body_prefix_base64: request_body_prefix_base64,
1710                body_suffix: request_body_suffix,
1711                body_suffix_base64: request_body_suffix_base64,
1712                body_prefix_not: request_body_prefix_not,
1713                body_prefix_not_base64: request_body_prefix_not_base64,
1714                body_suffix_not: request_body_suffix_not,
1715                body_suffix_not_base64: request_body_suffix_not_base64,
1716                body_matches: from_pattern_vec(value.request.body_matches),
1717
1718                // JSON Body-related fields
1719                json_body: value.request.json_body,
1720                json_body_not: value.request.json_body_not,
1721                json_body_includes: value.request.json_body_includes,
1722                json_body_excludes: value.request.json_body_excludes,
1723
1724                // Form URL-encoded fields
1725                form_urlencoded_tuple: from_string_pair_vec(value.request.form_urlencoded_tuple),
1726                form_urlencoded_tuple_not: from_string_pair_vec(
1727                    value.request.form_urlencoded_tuple_not,
1728                ),
1729                form_urlencoded_key_exists: value.request.form_urlencoded_tuple_exists,
1730                form_urlencoded_key_missing: value.request.form_urlencoded_tuple_missing,
1731                form_urlencoded_contains: to_name_value_string_pair_vec(
1732                    value.request.form_urlencoded_tuple_includes,
1733                ),
1734                form_urlencoded_excludes: to_name_value_string_pair_vec(
1735                    value.request.form_urlencoded_tuple_excludes,
1736                ),
1737                form_urlencoded_prefix: to_name_value_string_pair_vec(
1738                    value.request.form_urlencoded_tuple_prefix,
1739                ),
1740                form_urlencoded_suffix: to_name_value_string_pair_vec(
1741                    value.request.form_urlencoded_tuple_suffix,
1742                ),
1743                form_urlencoded_prefix_not: to_name_value_string_pair_vec(
1744                    value.request.form_urlencoded_tuple_prefix_not,
1745                ),
1746                form_urlencoded_suffix_not: to_name_value_string_pair_vec(
1747                    value.request.form_urlencoded_tuple_suffix_not,
1748                ),
1749                form_urlencoded_matches: to_name_value_pattern_pair_vec(
1750                    value.request.form_urlencoded_tuple_matches,
1751                ),
1752
1753                form_urlencoded_count: to_key_value_pattern_count_triple_vec(
1754                    value.request.form_urlencoded_tuple_count,
1755                ),
1756            },
1757            then: StaticHTTPResponse {
1758                status: value.response.status,
1759                header: from_string_pair_vec(value.response.headers),
1760                body: response_body,
1761                body_base64: response_body_base64,
1762                // Reason for the cast to u64: The Duration::as_millis method returns the total
1763                // number of milliseconds contained within the Duration as a u128. This is
1764                // because Duration::as_millis needs to handle larger values that
1765                // can result from multiplying the seconds (stored internally as a u64)
1766                // by 1000 and adding the milliseconds (also a u64), potentially
1767                // exceeding the u64 limit.
1768                delay: value.response.delay,
1769            },
1770        })
1771    }
1772}
1773
1774/// Represents an HTTP method.
1775#[derive(Serialize, Deserialize, Debug)]
1776pub enum Method {
1777    GET,
1778    HEAD,
1779    POST,
1780    PUT,
1781    DELETE,
1782    CONNECT,
1783    OPTIONS,
1784    TRACE,
1785    PATCH,
1786}
1787
1788impl PartialEq<Method> for http::method::Method {
1789    fn eq(&self, other: &Method) -> bool {
1790        self.to_string().to_uppercase() == other.to_string().to_uppercase()
1791    }
1792}
1793
1794impl FromStr for Method {
1795    type Err = String;
1796
1797    fn from_str(input: &str) -> Result<Self, Self::Err> {
1798        match input.to_uppercase().as_str() {
1799            "GET" => Ok(Method::GET),
1800            "HEAD" => Ok(Method::HEAD),
1801            "POST" => Ok(Method::POST),
1802            "PUT" => Ok(Method::PUT),
1803            "DELETE" => Ok(Method::DELETE),
1804            "CONNECT" => Ok(Method::CONNECT),
1805            "OPTIONS" => Ok(Method::OPTIONS),
1806            "TRACE" => Ok(Method::TRACE),
1807            "PATCH" => Ok(Method::PATCH),
1808            _ => Err(format!("Invalid HTTP method {}", input)),
1809        }
1810    }
1811}
1812
1813impl From<&str> for Method {
1814    fn from(value: &str) -> Self {
1815        value
1816            .parse()
1817            .expect(&format!("Cannot parse HTTP method from string {:?}", value))
1818    }
1819}
1820
1821impl std::fmt::Display for Method {
1822    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1823        std::fmt::Debug::fmt(self, f)
1824    }
1825}