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
This commit is contained in:
Paul van Tilburg 2023-01-16 19:57:05 +01:00
parent 93e8295c96
commit e268a6ebca
Signed by: paul
GPG Key ID: C6DE073EDA9EEC4D
2 changed files with 30 additions and 8 deletions

View File

@ -35,9 +35,12 @@ pub(crate) enum Error {
/// This usually indicates that the service needs to login again. /// This usually indicates that the service needs to login again.
#[error("not/no longer authorized")] #[error("not/no longer authorized")]
NotAuthorized, NotAuthorized,
/// The services encountered some other API request error. /// The service encountered some other API request error.
#[error("API request error: {0}")] #[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. /// Type alias for service results.

View File

@ -13,7 +13,10 @@ use rocket::async_trait;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use url::ParseError; use url::ParseError;
use crate::{services::Result, Status}; use crate::{
services::{Error, Result},
Status,
};
/// The base URL of Hoymiles API gateway. /// The base URL of Hoymiles API gateway.
const BASE_URL: &str = "https://global.hoymiles.com/platform/api/gateway"; const BASE_URL: &str = "https://global.hoymiles.com/platform/api/gateway";
@ -300,9 +303,17 @@ impl super::Service for Service {
.await?; .await?;
let login_response_data = match login_response.error_for_status() { let login_response_data = match login_response.error_for_status() {
Ok(res) => { Ok(res) => {
let api_response = res.json::<ApiLoginResponse>().await?; let login_response = res.json::<ApiLoginResponse>().await?;
eprintln!("api_response = {:#?}", &api_response); match login_response.status {
api_response.data.expect("No API response data found") 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()), Err(err) => return Err(err.into()),
}; };
@ -330,8 +341,16 @@ impl super::Service for Service {
let api_data = match api_response.error_for_status() { let api_data = match api_response.error_for_status() {
Ok(res) => { Ok(res) => {
let api_response = res.json::<ApiDataResponse>().await?; let api_response = res.json::<ApiDataResponse>().await?;
eprintln!("api_response = {:#?}", &api_response); match api_response.status {
api_response.data.expect("No API response data found") 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()), Err(err) => return Err(err.into()),
}; };