use axum::body::Body; use axum::extract::Request; use log::{error, info}; use crate::config::Config; use reqwest::Response; #[derive(serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct GSDLoginRequestDTO { user: String, pass: String, app_names: Vec, } #[derive(serde::Deserialize, serde::Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct GSDLoginResponseDTO { status: GSDLoginResponseStatusDTO, data: Option, } #[derive(serde::Deserialize, serde::Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct GSDLoginResponseDataDTO { session_id: String, } #[derive(serde::Deserialize, serde::Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct GSDLoginResponseStatusDTO { internal_status: String, status_message: String, } #[derive(Clone)] pub struct GSDService { host_url: String, app_names: Vec, app_key: String, username: String, password: String, } #[derive(Debug)] pub enum GSDServiceError { LoginFailed, LoginResponseParsingFailed, RequestError(String), } impl GSDService { pub async fn get_session(&self) -> Result { info!("Session: No session found. Generate session from GSD server {}", self.host_url); let dto = GSDLoginRequestDTO { user: self.username.clone(), pass: self.password.clone(), app_names: self.app_names.clone(), }; let response = reqwest::Client::new() .post(format!("{}/v1/login", self.host_url.clone())) .header("appKey", self.app_key.as_str()) .header("Content-Type", "application/json") .json(&dto) .send() .await .map_err(|e| { error!("Session: error request to GSD: {}", e); GSDServiceError::LoginFailed })?; let response_dto: GSDLoginResponseDTO = response .json() .await .map_err(|e| { error!("Session: error request to GSD: {}", e); GSDServiceError::LoginResponseParsingFailed })?; if response_dto.status.internal_status != "0" { error!("Session: error message from GSD: {}", response_dto.status.status_message); Err(GSDServiceError::LoginFailed) } else { match response_dto.data { Some(data) => { info!("Session: successfully obtained session with session id {}", &data.session_id); Ok(data.session_id.clone()) }, None => { error!("Session: failed to obtain session id. No session id in request found."); Err(GSDServiceError::LoginResponseParsingFailed) }, } } } pub async fn forward_post_request(&self, request: Request) -> Result { let (parts, body) = request.into_parts(); reqwest::Client::new() .post(format!("{}{}", self.host_url.clone(), parts.uri)) .headers(parts.headers) .body(axum::body::to_bytes(body, usize::MAX).await.unwrap()) .send() .await .map_err(|e| GSDServiceError::RequestError(e.to_string())) } } impl From<&Config> for GSDService { fn from(config: &Config) -> Self { Self { host_url: config.gsd_rest_url.clone(), app_names: config.gsd_app_names.clone(), app_key: config.gsd_app_key.clone(), username: config.gsd_user.clone(), password: config.gsd_password.clone(), } } }