lemon_bugsnag_rs 0.1.2

A library for interacting with the BugSnag error-reporting and sessions APIs.
Documentation
use std::collections::HashMap;

use serde::Serialize;

/// Struct corresponding to the `events -> request` key in the BugSnag
/// error-reporting API payload. Detauls about web request from the client
/// experiencing the error
///
/// ```
/// use lemon_bugsnag_rs::error::payload::events::Request;
///
/// let request = Request::default();
/// ```
#[derive(Clone, Debug, Default, Serialize, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Request {
    /// The client's IP address
    pub client_ip: Option<String>,
    /// The send requests headers
    pub headers: Option<HashMap<String, String>>,
    /// The HTTP method of the request
    pub http_method: Option<String>,
    /// The url of the request
    pub url: Option<String>,
    /// The HTTP referer
    pub referer: Option<String>,
}

#[cfg_attr(docsrs, doc(cfg(feature = "optional-builders")))]
#[cfg(feature = "optional-builders")]
impl Request {
    /// Retrieve an [RequestBuilder].
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    ///
    /// let mut rb = Request::builder();
    /// ```
    pub fn builder() -> RequestBuilder {
        RequestBuilder::default()
    }
}

/// Builder used to generate an [Request] struct.
///
/// ```
/// use lemon_bugsnag_rs::error::payload::events::Request;
///
/// // Generally, you get the builder this way, rather than creating an
/// // ExceptionBuilder struct manually.
/// let mut rb = Request::builder();
/// ```
#[cfg_attr(docsrs, doc(cfg(feature = "optional-builders")))]
#[cfg(feature = "optional-builders")]
#[derive(Default)]
pub struct RequestBuilder {
    request: Request,
}

#[cfg_attr(docsrs, doc(cfg(feature = "optional-builders")))]
#[cfg(feature = "optional-builders")]
impl RequestBuilder {
    /// Set the client_ip field of the Request struct.
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    /// let mut rb = Request::builder();
    ///
    /// // Give the client_ip a value.
    /// rb.set_client_ip("123.45.67.89");
    ///
    /// // Unset the client_ip.
    /// rb.set_client_ip(None);
    /// ```
    pub fn set_client_ip<'a>(
        &mut self,
        client_ip: impl Into<Option<&'a str>>,
    ) -> &mut Self {
        self.request.client_ip = client_ip.into().map(|item| item.into());

        self
    }

    /// Set the headers field of the Request struct.
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    /// use std::collections::HashMap;
    /// let mut rb = Request::builder();
    ///
    /// let test_headers: HashMap<String, String> = [(
    ///     "Header".to_string(),
    ///     "Header Value".to_string()
    /// )].into();
    ///
    /// // Give the headers a value.
    /// rb.set_headers(test_headers);
    ///
    /// // Unset the headers.
    /// rb.set_headers(None);
    /// ```
    pub fn set_headers<'a>(
        &mut self,
        headers: impl Into<Option<HashMap<String, String>>>,
    ) -> &mut Self {
        self.request.headers = headers.into();

        self
    }

    /// Set the http_method field of the Request struct.
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    /// let mut rb = Request::builder();
    ///
    /// // Give the http_method a value.
    /// rb.set_http_method("GET");
    ///
    /// // Unset the http_method.
    /// rb.set_http_method(None);
    /// ```
    pub fn set_http_method<'a>(
        &mut self,
        http_method: impl Into<Option<&'a str>>,
    ) -> &mut Self {
        self.request.http_method = http_method.into().map(|item| item.into());

        self
    }

    /// Set the url field of the Request struct.
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    /// let mut rb = Request::builder();
    ///
    /// // Give the url a value.
    /// rb.set_url("https://google.com");
    ///
    /// // Unset the url.
    /// rb.set_url(None);
    /// ```
    pub fn set_url<'a>(
        &mut self,
        url: impl Into<Option<&'a str>>,
    ) -> &mut Self {
        self.request.url = url.into().map(|item| item.into());

        self
    }

    /// Set the referer field of the Request struct.
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    /// let mut rb = Request::builder();
    ///
    /// // Give the referer a value.
    /// rb.set_referer("https://google.com");
    ///
    /// // Unset the referer.
    /// rb.set_referer(None);
    /// ```
    pub fn set_referer<'a>(
        &mut self,
        referer: impl Into<Option<&'a str>>,
    ) -> &mut Self {
        self.request.referer = referer.into().map(|item| item.into());

        self
    }

    /// Generate an [Request] struct using the options you set using the
    /// builder.
    ///
    /// ```
    /// use lemon_bugsnag_rs::error::payload::events::Request;
    /// use std::collections::HashMap;
    ///
    /// let test_headers: HashMap<String, String> = [(
    ///     "Header".to_string(),
    ///     "Header Value".to_string()
    /// )].into();
    ///
    /// let mut rb = Request::builder();
    ///
    /// rb.set_client_ip("123.45.67.89")
    ///     .set_headers(test_headers)
    ///     .set_http_method("GET")
    ///     .set_url("https://google.com")
    ///     .set_referer(None);
    ///
    /// let request = rb.build();
    /// ```
    pub fn build(&self) -> Request {
        self.request.clone()
    }
}

#[cfg(test)]
mod test {
    #[cfg(feature = "optional-builders")]
    #[test]
    pub fn test_error_payload_events_request_builder() {
        use crate::error::payload::events::Request;
        use std::collections::HashMap;

        let test_headers: HashMap<String, String> =
            [("Header-name".to_string(), "Header value".to_string())].into();

        let test_request = Request {
            client_ip: "Client IP".to_string().into(),
            headers: test_headers.into(),
            http_method: "Http Method".to_string().into(),
            url: "Url".to_string().into(),
            referer: "".to_string().into(),
        };

        let mut request_builder = Request::builder();
        request_builder
            .set_client_ip(test_request.client_ip.clone().as_deref())
            .set_headers(test_request.headers.clone())
            .set_http_method(test_request.http_method.clone().as_deref())
            .set_referer(test_request.referer.clone().as_deref())
            .set_url(test_request.url.clone().as_deref());
        let request = request_builder.build();

        assert_eq!(test_request, request);
    }
}