rrw 0.1.2

A crate to easily build clients for REST-APIs.
Documentation
//! Authentication of requests
//!
//! The general interface for authenticating requests is the [Authenticator]. One example
//! implementation is the [HeaderAuthenticator] that sets the authentication in the header.
use reqwest::RequestBuilder;

/// Authenticate a request.
pub trait Authenticator {
    /// Modify a [RequestBuilder] to be authenticated.
    fn authenticate(&self, request: RequestBuilder) -> RequestBuilder;
}

/// Authenticate a request by setting a key-value pair in the head of the request.
pub struct HeaderAuthenticator {
    key: String,
    token: String,
}

impl HeaderAuthenticator {
    /// Create a new [HeaderAuthenticator] with the given header key (usually `Authentication`,
    /// `PRIVATE-TOKEN` or similar) and the value as the given token.
    pub fn new<S1: AsRef<str>, S2: AsRef<str>>(key: S1, token: S2) -> Self {
        Self {
            key: key.as_ref().to_owned(),
            token: token.as_ref().to_owned(),
        }
    }
}

impl Authenticator for HeaderAuthenticator {
    fn authenticate(&self, request: RequestBuilder) -> RequestBuilder {
        request.header(&self.key, &self.token)
    }
}

#[cfg(test)]
mod test {
    use crate::{Error, RestConfigBuilder, RestRequest, StandardRestError};

    use super::*;

    use httpmock::prelude::*;
    use serde::{Deserialize, Serialize};

    #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
    struct Json {
        key: String,
    }

    #[tokio::test]
    async fn header_authenticator() -> Result<(), Error<StandardRestError>> {
        let server = MockServer::start();

        let mock = server.mock(|when, then| {
            when.method(GET)
                .path("/test")
                .header("PRIVATE-TOKEN", "123456");
            then.status(200)
                .header("content-type", "application/json; charset=UTF-8")
                .body(r#"{"key":"value"}"#);
        });

        let authenticator = HeaderAuthenticator::new("PRIVATE-TOKEN", "123456");

        let config = RestConfigBuilder::new(server.base_url())
            .authenticator(authenticator)
            .build();
        let query: Json = config
            .execute(&RestRequest::<(), ()>::get("/test").authenticate())
            .await?;

        mock.assert();
        assert_eq!(
            query,
            Json {
                key: "value".to_string()
            }
        );

        Ok(())
    }
}