riva 1.0.0

Server-backed Rust client for the Riva proxy (YouTube and SoundCloud).
Documentation
use std::env;

use url::Url;

use crate::error::RivaError;

pub const DEFAULT_RIVA_BASE_URL: &str = "https://riva.resonix.dev";

const BASE_URL_ENV_KEYS: &[&str] = &["RIVA_BASE_URL", "RIVA_SERVER_URL", "RIVA_URL"];
const SECRET_ENV_KEYS: &[&str] = &["RIVA_ACCESS_SECRET", "RIVA_API_KEY", "RIVA_TOKEN"];

#[derive(Debug, Clone)]
pub struct RivaConfig {
    pub base_url: Url,
    pub access_secret: Option<String>,
}

impl Default for RivaConfig {
    fn default() -> Self {
        Self {
            base_url: Url::parse(DEFAULT_RIVA_BASE_URL).expect("default URL is valid"),
            access_secret: None,
        }
    }
}

impl RivaConfig {
    pub fn from_env() -> Result<Self, RivaError> {
        let base_url =
            env_value(BASE_URL_ENV_KEYS).unwrap_or_else(|| DEFAULT_RIVA_BASE_URL.to_owned());

        let mut config = Self::new(base_url)?;
        config.access_secret = env_value(SECRET_ENV_KEYS);
        Ok(config)
    }

    pub fn new(base_url: impl AsRef<str>) -> Result<Self, RivaError> {
        let mut parsed = Url::parse(base_url.as_ref()).map_err(RivaError::InvalidBaseUrl)?;
        if !parsed.path().ends_with('/') {
            let path = format!("{}/", parsed.path());
            parsed.set_path(&path);
        }

        Ok(Self {
            base_url: parsed,
            access_secret: None,
        })
    }

    pub fn with_access_secret(mut self, access_secret: impl Into<String>) -> Self {
        self.access_secret = Some(access_secret.into());
        self
    }
}

fn env_value(keys: &[&str]) -> Option<String> {
    keys.iter()
        .find_map(|key| env::var(key).ok())
        .map(|value| value.trim().to_string())
        .filter(|value| !value.is_empty())
}

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

    #[test]
    fn new_adds_trailing_slash_to_base_url() {
        let config = RivaConfig::new("https://example.com/api").expect("config should build");
        assert_eq!(config.base_url.as_str(), "https://example.com/api/");
    }
}