From 19d87e6ee3ae44c5b1c853adf00329a894778b06 Mon Sep 17 00:00:00 2001 From: Jake Swenson Date: Sun, 16 May 2021 22:23:37 -0700 Subject: feat: adding proper error type with snafu (#8) --- src/lib.rs | 56 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index c97ee48..c74aadf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,13 +3,29 @@ use crate::models::{Database, DatabaseId, ListResponse, Object, Page}; use reqwest::header::{HeaderMap, HeaderValue}; use reqwest::{header, Client, ClientBuilder, RequestBuilder}; use serde::de::DeserializeOwned; +use snafu::{ResultExt, Snafu}; mod models; -const NOTION_API_VERSION: &'static str = "2021-05-13"; +const NOTION_API_VERSION: &str = "2021-05-13"; -// todo: replace with proper snafu error -pub type NotionApiClientError = Box; +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("Invalid Notion API Token: {}", source))] + InvalidApiToken { + source: reqwest::header::InvalidHeaderValue, + }, + #[snafu(display("Unable to build reqwest HTTP client: {}", source))] + ErrorBuildingClient { source: reqwest::Error }, + #[snafu(display("Error sending HTTP request: {}", source))] + RequestFailed { source: reqwest::Error }, + + #[snafu(display("Error reading response: {}", source))] + ResponseError { source: reqwest::Error }, + + #[snafu(display("Error parsing json response: {}", source))] + JsonParseError { source: serde_json::Error }, +} pub trait Identifiable { // There should only be one way to identify an object @@ -22,40 +38,48 @@ pub struct NotionApi { } impl NotionApi { - pub fn new(api_token: String) -> Result { + pub fn new(api_token: String) -> Result { let mut headers = HeaderMap::new(); headers.insert( "Notion-Version", HeaderValue::from_static(NOTION_API_VERSION), ); - let mut auth_value = HeaderValue::from_str(&format!("Bearer {}", api_token))?; + let mut auth_value = + HeaderValue::from_str(&format!("Bearer {}", api_token)).context(InvalidApiToken)?; auth_value.set_sensitive(true); headers.insert(header::AUTHORIZATION, auth_value); - let client = ClientBuilder::new().default_headers(headers).build()?; + let client = ClientBuilder::new() + .default_headers(headers) + .build() + .context(ErrorBuildingClient)?; Ok(Self { client }) } - async fn make_json_request(request: RequestBuilder) -> Result + async fn make_json_request(request: RequestBuilder) -> Result where T: DeserializeOwned, { - let json = request.send().await?.text().await?; + let json = request + .send() + .await + .context(RequestFailed)? + .text() + .await + .context(ResponseError)?; #[cfg(test)] { println!("JSON: {}", json); - dbg!(serde_json::from_str::(&json)?); + dbg!(serde_json::from_str::(&json).context(JsonParseError)?); } - let result = serde_json::from_str(&json)?; + let result = serde_json::from_str(&json).context(JsonParseError)?; Ok(result) } /// This method is apparently deprecated/"not recommended" - pub async fn list_databases( - &self, - ) -> Result, Box> { + pub async fn list_databases(&self) -> Result, Error> { let builder = self.client.get("https://api.notion.com/v1/databases"); Ok(NotionApi::make_json_request(builder).await?) @@ -64,7 +88,7 @@ impl NotionApi { pub async fn search>( &self, query: T, - ) -> Result, NotionApiClientError> { + ) -> Result, Error> { Ok(NotionApi::make_json_request( self.client .post("https://api.notion.com/v1/search") @@ -76,7 +100,7 @@ impl NotionApi { pub async fn get_database>( &self, database_id: T, - ) -> Result { + ) -> Result { Ok(NotionApi::make_json_request(self.client.get(format!( "https://api.notion.com/v1/databases/{}", database_id.id().id() @@ -88,7 +112,7 @@ impl NotionApi { &self, database: D, query: T, - ) -> Result, NotionApiClientError> + ) -> Result, Error> where T: Into, D: Identifiable, -- cgit v1.2.3