Handle errors from the API more gracefully
This commit is contained in:
parent
6f4c408a26
commit
353eb865db
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -101,7 +101,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cta-api"
|
name = "cta-api"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cta-api"
|
name = "cta-api"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
description = "CTA API Client"
|
description = "CTA API Client"
|
||||||
authors = ["Joey Hines joey@ahines.net"]
|
authors = ["Joey Hines joey@ahines.net"]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::models::Response;
|
|
||||||
use crate::models::eta::{EtaRequest, EtaResp};
|
use crate::models::eta::{EtaRequest, EtaResp};
|
||||||
use crate::models::follow::{FollowRequest, FollowResp};
|
use crate::models::follow::{FollowRequest, FollowResp};
|
||||||
use crate::models::route::{RouteRequest, RouteResp};
|
use crate::models::route::{RouteRequest, RouteResp};
|
||||||
|
use crate::models::{CTAResponse, Response};
|
||||||
use reqwest::{Client, Url};
|
use reqwest::{Client, Url};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -18,6 +18,8 @@ pub enum Error {
|
|||||||
ReqwestFailure(#[from] reqwest::Error),
|
ReqwestFailure(#[from] reqwest::Error),
|
||||||
#[error("URL parse failure: {0}")]
|
#[error("URL parse failure: {0}")]
|
||||||
UrlParseError(#[from] url::ParseError),
|
UrlParseError(#[from] url::ParseError),
|
||||||
|
#[error("Got error number '{0}': {1}")]
|
||||||
|
CtaError(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CTAClient {
|
pub struct CTAClient {
|
||||||
@ -35,7 +37,7 @@ impl CTAClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn make_request<T: Serialize, V: for<'a> Deserialize<'a>>(
|
pub async fn make_request<T: Serialize, V: for<'a> Deserialize<'a> + CTAResponse>(
|
||||||
&mut self,
|
&mut self,
|
||||||
endpoint: &str,
|
endpoint: &str,
|
||||||
req: T,
|
req: T,
|
||||||
@ -53,6 +55,8 @@ impl CTAClient {
|
|||||||
.json()
|
.json()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
resp.ctatt.check_error()?;
|
||||||
|
|
||||||
Ok(resp.ctatt)
|
Ok(resp.ctatt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::models::Ctatt;
|
use crate::models::{CTAResponse, Ctatt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
@ -13,9 +13,16 @@ pub struct EtaRequest {
|
|||||||
pub struct EtaResp {
|
pub struct EtaResp {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub header: Ctatt,
|
pub header: Ctatt,
|
||||||
|
#[serde(default)]
|
||||||
pub eta: Vec<Eta>,
|
pub eta: Vec<Eta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CTAResponse for EtaResp {
|
||||||
|
fn get_header(&self) -> Ctatt {
|
||||||
|
self.header.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Eta {
|
pub struct Eta {
|
||||||
#[serde(rename = "staId")]
|
#[serde(rename = "staId")]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::models::Ctatt;
|
use crate::models::{CTAResponse, Ctatt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
@ -7,7 +7,7 @@ pub struct FollowRequest {
|
|||||||
pub run_number: u32,
|
pub run_number: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Default)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub lat: String,
|
pub lat: String,
|
||||||
pub lon: String,
|
pub lon: String,
|
||||||
@ -48,6 +48,14 @@ pub struct ScheduledStop {
|
|||||||
pub struct FollowResp {
|
pub struct FollowResp {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub header: Ctatt,
|
pub header: Ctatt,
|
||||||
|
#[serde(default)]
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
#[serde(default)]
|
||||||
pub eta: Vec<ScheduledStop>,
|
pub eta: Vec<ScheduledStop>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CTAResponse for FollowResp {
|
||||||
|
fn get_header(&self) -> Ctatt {
|
||||||
|
self.header.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,9 +3,10 @@ pub mod follow;
|
|||||||
pub mod route;
|
pub mod route;
|
||||||
pub mod train;
|
pub mod train;
|
||||||
|
|
||||||
|
use crate::Error;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct Ctatt {
|
pub struct Ctatt {
|
||||||
pub tmst: String,
|
pub tmst: String,
|
||||||
#[serde(rename = "errCd")]
|
#[serde(rename = "errCd")]
|
||||||
@ -14,7 +15,20 @@ pub struct Ctatt {
|
|||||||
pub err_nm: Option<String>,
|
pub err_nm: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait CTAResponse {
|
||||||
|
fn get_header(&self) -> Ctatt;
|
||||||
|
fn check_error(&self) -> Result<(), Error> {
|
||||||
|
let header = self.get_header();
|
||||||
|
|
||||||
|
if let Some(err_number) = header.err_nm {
|
||||||
|
Err(Error::CtaError(err_number, header.err_cd))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Response<T> {
|
pub struct Response<T: CTAResponse> {
|
||||||
pub ctatt: T,
|
pub ctatt: T,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::models::Ctatt;
|
|
||||||
use crate::models::train::Train;
|
use crate::models::train::Train;
|
||||||
|
use crate::models::{CTAResponse, Ctatt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
@ -18,5 +18,12 @@ pub struct Route {
|
|||||||
pub struct RouteResp {
|
pub struct RouteResp {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub header: Ctatt,
|
pub header: Ctatt,
|
||||||
|
#[serde(default)]
|
||||||
pub route: Vec<Route>,
|
pub route: Vec<Route>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CTAResponse for RouteResp {
|
||||||
|
fn get_header(&self) -> Ctatt {
|
||||||
|
self.header.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user