valorant_api_official 0.2.2

A library for interacting with the Official Valorant API.
Documentation
use std::collections::HashMap;
use std::str::FromStr;

use reqwest::RequestBuilder;
use serde::de::DeserializeOwned;
use url::Url;

use crate::errors::response_error::RequestError;
use crate::utils::credentials_manager::CredentialsManager;

pub(crate) async fn fetch_endpoint<D: DeserializeOwned>(
    credentials_manager: &CredentialsManager,
    http_client: &reqwest::Client,
    uri: Url,
    method: &str,
    body: &str,
    headers: &HashMap<String, String>,
) -> Result<D, RequestError> {
    let raw_result =
        fetch_endpoint_raw(credentials_manager, http_client, uri, method, body, headers).await?;
    raw_result.json().await.map_err(RequestError::from)
}

async fn fetch_endpoint_raw(
    credentials_manager: &CredentialsManager,
    http_client: &reqwest::Client,
    uri: Url,
    method: &str,
    body: &str,
    headers: &HashMap<String, String>,
) -> Result<reqwest::Response, RequestError> {
    let auth_headers = credentials_manager.get_auth_headers();
    let headers = headers
        .iter()
        .chain(auth_headers.iter())
        .map(|(key, value)| (key.clone(), value.clone()))
        .collect::<HashMap<String, String>>();

    let request = build_request(uri, http_client, method, body, &headers)?;

    let response = request.send().await.map_err(RequestError::from)?;
    let status = response.status();

    if !status.is_success() {
        return Err(RequestError::from((status.as_u16(), body.to_string())));
    }

    Ok(response)
}

fn build_request(
    uri: Url,
    http_client: &reqwest::Client,
    method: &str,
    body: &str,
    headers: &HashMap<String, String>,
) -> Result<RequestBuilder, RequestError> {
    let method =
        reqwest::Method::from_str(method).map_err(|e| RequestError::from(e.to_string()))?;
    Ok(http_client
        .request(method, uri)
        .body(body.to_string())
        .headers(
            headers
                .iter()
                .map(|(key, value)| {
                    (
                        reqwest::header::HeaderName::from_str(key)
                            .map_err(|e| RequestError::from(e.to_string())),
                        reqwest::header::HeaderValue::from_str(value)
                            .map_err(|e| RequestError::from(e.to_string())),
                    )
                })
                .filter_map(|(key, value)| match (key, value) {
                    (Ok(key), Ok(value)) => Some((key, value)),
                    _ => None,
                })
                .collect(),
        ))
}