dimo_rust_sdk/utils/
request.rs

1use crate::utils::get_credentials;
2use reqwest::{Client, Method};
3use serde_json::Value;
4use std::collections::HashMap;
5use std::error::Error;
6
7#[derive(serde::Serialize)]
8pub enum QueryValue {
9    Str(String),
10    Bool(bool),
11}
12
13#[derive(Debug, serde::Serialize)]
14pub enum BodyValue {
15    String(String),
16    Array(Vec<String>),
17}
18
19#[derive(Debug)]
20pub struct RequestParams {
21    pub method: Method,
22    pub base_url: String,
23    pub path: String,
24    pub query_params: Option<HashMap<String, String>>,
25    pub body: Option<HashMap<String, Value>>,
26    pub headers: Option<HashMap<String, String>>,
27}
28
29pub struct AuthRequestParams {
30    pub method: Method,
31    pub base_url: String,
32    pub path: String,
33    pub query_params: Option<HashMap<String, String>>,
34    pub body: Option<HashMap<String, Value>>,
35    pub headers: Option<HashMap<String, String>>,
36    pub token_type: String,
37}
38
39/// Builds the authorization header using the appropriate token from `get_credentials`.
40/// `token_type` should be either "developer" (for developer jwt) or "vehicle" (for vehicle jwt).
41fn build_auth_header(token_type: &str) -> Result<HashMap<String, String>, Box<dyn Error>> {
42    let credentials = get_credentials()?;
43
44    let token = match token_type {
45        "developer" => &credentials.developer_jwt,
46        "vehicle" => &credentials.vehicle_jwt,
47        _ => return Err("Invalid token type specified. Use 'developer' or 'vehicle'.".into()),
48    };
49
50    let mut headers = HashMap::new();
51    headers.insert("Authorization".to_string(), format!("Bearer {}", token));
52    Ok(headers)
53}
54
55pub async fn make_auth_request(params: AuthRequestParams) -> Result<Value, Box<dyn Error>> {
56    let auth_header = build_auth_header(&params.token_type)?;
57    let mut headers = params.headers.unwrap_or_default();
58    headers.extend(auth_header);
59
60    let request_params = RequestParams {
61        method: params.method,
62        base_url: params.base_url,
63        path: params.path,
64        query_params: params.query_params,
65        body: params.body,
66        headers: Some(headers),
67    };
68
69    make_request(request_params).await
70}
71
72pub async fn make_request(params: RequestParams) -> Result<Value, Box<dyn Error>> {
73    let client = Client::new();
74    let url = format!("{}{}", params.base_url, params.path);
75
76    let mut request_builder = match params.method {
77        Method::GET => client.get(&url),
78        Method::POST => client.post(&url),
79        Method::PATCH => client.patch(&url),
80        _ => return Err("Unsupported method".into()),
81    };
82
83    if let Some(ref query_params) = params.query_params {
84        request_builder = request_builder.query(&query_params);
85    };
86
87    let use_form_body = params
88        .headers
89        .as_ref()
90        .and_then(|headers| headers.get("Content-Type"))
91        .map(|value| value.eq_ignore_ascii_case("x-www-form-urlencoded"))
92        .unwrap_or(false);
93
94    if let Some(body) = params.body {
95        request_builder = if use_form_body {
96            request_builder.form(&body)
97        } else {
98            request_builder.json(&body)
99        };
100    }
101
102    if let Some(headers) = params.headers {
103        for (key, value) in headers {
104            request_builder = request_builder.header(&key, &value);
105        }
106    }
107
108    let response_result = request_builder.send().await;
109
110    match response_result {
111        Ok(resp) => {
112            if resp.status().is_success() {
113                let json_response = resp.json::<Value>().await?;
114                Ok(json_response)
115            } else {
116                let status = resp.status();
117                let error_text = resp
118                    .text()
119                    .await
120                    .unwrap_or_else(|_| "Unknown error".to_string());
121                Err(format!("Error {}: {}", status, error_text).into())
122            }
123        }
124        Err(err) => Err(format!("Request error: {}", err).into()),
125    }
126}