From e268a6ebca056786d5e6ccf0ba263d0c18e68546 Mon Sep 17 00:00:00 2001 From: Paul van Tilburg Date: Mon, 16 Jan 2023 19:57:05 +0100 Subject: [PATCH] Detect when API (login) responses are not correct * Introduce the `Error::Response` variant so services can raise errors if the API response are not valid but a relogin will not help * Indicate that a login failed for status (error) code 1 * Indicate that an API request failed and relogin is necessary for status code 1 or 100 * Raise an error on any non-zero status code otherwise with the message --- src/services.rs | 7 +++++-- src/services/hoymiles.rs | 31 +++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/services.rs b/src/services.rs index e7f8530..bae0948 100644 --- a/src/services.rs +++ b/src/services.rs @@ -35,9 +35,12 @@ pub(crate) enum Error { /// This usually indicates that the service needs to login again. #[error("not/no longer authorized")] NotAuthorized, - /// The services encountered some other API request error. + /// The service encountered some other API request error. #[error("API request error: {0}")] - Request(#[from] reqwest::Error) + Request(#[from] reqwest::Error), + /// The service encountered an unsupported API response. + #[error("API service error: {0}")] + Response(String), } /// Type alias for service results. diff --git a/src/services/hoymiles.rs b/src/services/hoymiles.rs index 6e43170..5121d07 100644 --- a/src/services/hoymiles.rs +++ b/src/services/hoymiles.rs @@ -13,7 +13,10 @@ use rocket::async_trait; use serde::{Deserialize, Deserializer, Serialize}; use url::ParseError; -use crate::{services::Result, Status}; +use crate::{ + services::{Error, Result}, + Status, +}; /// The base URL of Hoymiles API gateway. const BASE_URL: &str = "https://global.hoymiles.com/platform/api/gateway"; @@ -300,9 +303,17 @@ impl super::Service for Service { .await?; let login_response_data = match login_response.error_for_status() { Ok(res) => { - let api_response = res.json::().await?; - eprintln!("api_response = {:#?}", &api_response); - api_response.data.expect("No API response data found") + let login_response = res.json::().await?; + match login_response.status { + 0 => login_response.data.expect("No API response data found"), + 1 => return Err(Error::NotAuthorized), + _ => { + return Err(Error::Response(format!( + "{} ({})", + login_response.message, login_response.status + ))) + } + } } Err(err) => return Err(err.into()), }; @@ -330,8 +341,16 @@ impl super::Service for Service { let api_data = match api_response.error_for_status() { Ok(res) => { let api_response = res.json::().await?; - eprintln!("api_response = {:#?}", &api_response); - api_response.data.expect("No API response data found") + match api_response.status { + 0 => api_response.data.expect("No API response data found"), + 1 | 100 => return Err(Error::NotAuthorized), + _ => { + return Err(Error::Response(format!( + "{} ({})", + api_response.message, api_response.status + ))) + } + } } Err(err) => return Err(err.into()), };