edgee-sdk 1.6.2

The full-stack edge platform for your edge oriented applications
Documentation
/// Generates a token from a hostname.
///
/// This function generates a token by computing the MD5 hash of the provided hostname
/// and formatting it as a lowercase hexadecimal string.
///
/// # Arguments
///
/// * `hostname` - A string slice containing the hostname to generate a token for
///
/// # Returns
///
/// * `String` - The generated token as a 32-character lowercase hexadecimal string
///
/// # Examples
///
/// ```
/// let hostname = "example.com";
/// let token = edgee_sdk::token::generate(hostname);
/// assert_eq!(token.len(), 32);
/// ```
pub fn generate(hostname: &str) -> String {
    format!("{:x}", md5::compute(hostname))
}

/// Validates a token from an authorization header against a hostname.
///
/// This function checks if a given authorization header contains a valid token for the specified hostname.
/// The token must be in the format "Bearer <token>" where <token> is a 32-character MD5 hash of the hostname.
///
/// # Arguments
///
/// * `hostname` - A string slice containing the hostname to validate against
/// * `authorization_header` - A string slice containing the full authorization header value
///
/// # Returns
///
/// * `bool` - Returns true if the token is valid for the hostname, false otherwise
///
/// # Examples
///
/// ```
/// let hostname = "example.com";
/// let auth_header = "Bearer d41d8cd98f00b204e9800998ecf8427e";
/// let is_valid = edgee_sdk::token::validate(hostname, auth_header);
/// ```
pub fn validate(hostname: &str, authorization_header: &str) -> bool {
    if !authorization_header.starts_with("Bearer ") {
        return false;
    }

    let token = &authorization_header["Bearer ".len()..];

    if token.len() != 32 {
        return false;
    }

    let token_md5 = format!("{:x}", md5::compute(hostname));

    token == token_md5
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_token() {
        let hostname = "example.com";
        let token = generate(hostname);

        // Check token length
        assert_eq!(token.len(), 32);

        // Check deterministic output
        assert_eq!(generate(hostname), generate(hostname));

        // Known value test
        assert_eq!(
            generate("test.com"),
            "c97c1b3671fef2055e175ca2154d217a".to_string()
        );
    }

    #[test]
    fn test_validate_token() {
        let hostname = "example.com";
        let token = generate(hostname);
        let valid_header = format!("Bearer {}", token);

        // Test valid token
        assert!(validate(hostname, &valid_header));

        // Test invalid bearer format
        assert!(!validate(hostname, &token));
        assert!(!validate(hostname, "bearer 123"));
        assert!(!validate(hostname, "Basic 123"));
        assert!(!validate(hostname, ""));

        // Test invalid token length
        assert!(!validate(hostname, "Bearer 123"));
        assert!(!validate(
            hostname,
            "Bearer 123456789012345678901234567890123"
        )); // 33 chars

        // Test wrong token
        assert!(!validate(
            hostname,
            "Bearer 0000000000000000000000000000000"
        ));

        // Test different hostname
        let other_token = generate("other.com");
        assert!(!validate(hostname, &format!("Bearer {}", other_token)));
    }
}