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]]
|
||||
name = "cta-api"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cta-api"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
edition = "2024"
|
||||
description = "CTA API Client"
|
||||
authors = ["Joey Hines joey@ahines.net"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::models::Response;
|
||||
use crate::models::eta::{EtaRequest, EtaResp};
|
||||
use crate::models::follow::{FollowRequest, FollowResp};
|
||||
use crate::models::route::{RouteRequest, RouteResp};
|
||||
use crate::models::{CTAResponse, Response};
|
||||
use reqwest::{Client, Url};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
@ -18,6 +18,8 @@ pub enum Error {
|
||||
ReqwestFailure(#[from] reqwest::Error),
|
||||
#[error("URL parse failure: {0}")]
|
||||
UrlParseError(#[from] url::ParseError),
|
||||
#[error("Got error number '{0}': {1}")]
|
||||
CtaError(String, String),
|
||||
}
|
||||
|
||||
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,
|
||||
endpoint: &str,
|
||||
req: T,
|
||||
@ -53,6 +55,8 @@ impl CTAClient {
|
||||
.json()
|
||||
.await?;
|
||||
|
||||
resp.ctatt.check_error()?;
|
||||
|
||||
Ok(resp.ctatt)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::models::Ctatt;
|
||||
use crate::models::{CTAResponse, Ctatt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
@ -13,9 +13,16 @@ pub struct EtaRequest {
|
||||
pub struct EtaResp {
|
||||
#[serde(flatten)]
|
||||
pub header: Ctatt,
|
||||
#[serde(default)]
|
||||
pub eta: Vec<Eta>,
|
||||
}
|
||||
|
||||
impl CTAResponse for EtaResp {
|
||||
fn get_header(&self) -> Ctatt {
|
||||
self.header.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Eta {
|
||||
#[serde(rename = "staId")]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::models::Ctatt;
|
||||
use crate::models::{CTAResponse, Ctatt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
@ -7,7 +7,7 @@ pub struct FollowRequest {
|
||||
pub run_number: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Deserialize, Debug, Default)]
|
||||
pub struct Position {
|
||||
pub lat: String,
|
||||
pub lon: String,
|
||||
@ -48,6 +48,14 @@ pub struct ScheduledStop {
|
||||
pub struct FollowResp {
|
||||
#[serde(flatten)]
|
||||
pub header: Ctatt,
|
||||
#[serde(default)]
|
||||
pub position: Position,
|
||||
#[serde(default)]
|
||||
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 train;
|
||||
|
||||
use crate::Error;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct Ctatt {
|
||||
pub tmst: String,
|
||||
#[serde(rename = "errCd")]
|
||||
@ -14,7 +15,20 @@ pub struct Ctatt {
|
||||
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)]
|
||||
pub struct Response<T> {
|
||||
pub struct Response<T: CTAResponse> {
|
||||
pub ctatt: T,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::models::Ctatt;
|
||||
use crate::models::train::Train;
|
||||
use crate::models::{CTAResponse, Ctatt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
@ -18,5 +18,12 @@ pub struct Route {
|
||||
pub struct RouteResp {
|
||||
#[serde(flatten)]
|
||||
pub header: Ctatt,
|
||||
#[serde(default)]
|
||||
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