diff --git a/Cargo.toml b/Cargo.toml index 0c734e2..356be0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -request = [] +request = ["surf/h1-client-rustls"] convert_from_notion = [] [dependencies] @@ -19,7 +19,4 @@ log = "0.4.20" regex = "1.7.1" serde = { version = "^1.0", features = ["derive"], default-features = false } serde_json = { version = "^1.0", features = ["raw_value"], default-features = false } -surf = { version = "2.3.2", default_features = false, features = ["h1-client-rustls"] } - -[dev-dependencies] -tokio = { version = "1.28.1", features = ["macros"] } +surf = { version = "2.3.2", default_features = false } diff --git a/src/lib.rs b/src/lib.rs index a783287..5e95502 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ use serde::de::Error as SerdeError; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::json; use serde_json::Value; +use surf::http::StatusCode; use futures_core::future::BoxFuture; @@ -20,14 +21,15 @@ lazy_static! { const NOTION_VERSION: &str = "2022-06-28"; pub type Result = std::result::Result; -pub type Callback = dyn Fn(&mut surf::RequestBuilder) -> BoxFuture<'_, std::result::Result> +pub type Callback = dyn Fn(surf::RequestBuilder) -> BoxFuture<'static, std::result::Result> + 'static + Send + Sync; #[derive(Debug)] pub enum Error { - Http(surf::Error, Option), + Http(StatusCode, surf::Response), + Surf(surf::Error), Deserialization(serde_json::Error, Option), ChronoParse(chrono::ParseError), UnexpectedType, @@ -41,7 +43,7 @@ impl std::fmt::Display for Error { impl From for Error { fn from(error: surf::Error) -> Self { - Error::Http(error, None) + Error::Surf(error) } } @@ -73,6 +75,7 @@ impl From for Error { #[cfg(feature = "request")] fn get_http_client(notion_api_key: &str) -> surf::Client { + log::trace!("Readying HTTP Client"); surf::Config::new() .add_header("Authorization", format!("Bearer {notion_api_key}")) .expect("to add Authorization header") @@ -114,8 +117,8 @@ impl ClientBuilder { pub fn custom_request(mut self, callback: F) -> Self where for<'c> F: Fn( - &'c mut surf::RequestBuilder, - ) -> BoxFuture<'c, std::result::Result> + surf::RequestBuilder, + ) -> BoxFuture<'static, std::result::Result> + 'static + Send + Sync, @@ -129,17 +132,17 @@ impl ClientBuilder { pub fn build(self) -> Client { let notion_api_key = self.api_key.expect("api_key to be set"); - let request_handler = self.custom_request.unwrap_or(Arc::new( - |request_builder: &mut surf::RequestBuilder| { - Box::pin(async move { - // let request = request_builder - // .clone() - // .expect("non-stream body request clone to succeed"); + let request_handler = + self.custom_request + .unwrap_or(Arc::new(|request_builder: surf::RequestBuilder| { + Box::pin(async move { + // let request = request_builder + // .clone() + // .expect("non-stream body request clone to succeed"); - request_builder.await - }) - }, - )); + request_builder.await + }) + })); let http_client = Arc::from(get_http_client(¬ion_api_key)); @@ -186,25 +189,20 @@ impl<'a> Client { self, options: SearchOptions<'b>, ) -> Result> { - let mut request = self + let request = self .http_client .post("https://api.notion.com/v1/search") .body_json(&options) .expect("to parse JSON for doing `search`"); - let mut response = (self.request_handler)(&mut request) + let mut response = (self.request_handler)(request) .await .expect("to request through a request handler"); - Ok(response.body_json().await?) - // TODO: re-implement wrong return from Notion - // match response { - // Ok(_) => Ok(response.body_json().await?), - // Err(error) => { - // let body = response.body_json::().await?; - // Err(Error::Http(error, Some(body))) - // } - // } + match response.status() { + StatusCode::Ok => Ok(response.body_json().await?), + status => Err(Error::Http(status, response)), + } } } @@ -225,18 +223,13 @@ impl Pages { page_id = options.page_id ); - let mut request = self.http_client.get(url); + let request = self.http_client.get(url); + let mut response = (self.request_handler)(request).await?; - let mut response = (self.request_handler)(&mut request).await?; - - Ok(response.body_json().await?) - // match response.error_for_status_ref() { - // Ok(_) => Ok(response.json().await?), - // Err(error) => { - // let body = response.json::().await?; - // Err(Error::Http(error, Some(body))) - // } - // } + match response.status() { + StatusCode::Ok => Ok(response.body_json().await?), + status => Err(Error::Http(status, response)), + } } } @@ -274,19 +267,14 @@ impl BlockChildren { block_id = options.block_id ); - let mut request = self.http_client.get(&url); + let request = self.http_client.get(&url); - let mut response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(request).await?; - Ok(response.body_json().await?) - - // match response.error_for_status_ref() { - // Ok(_) => Ok(response.json().await?), - // Err(error) => { - // let body = response.json::().await?; - // Err(Error::Http(error, Some(body))) - // } - // } + match response.status() { + StatusCode::Ok => Ok(response.body_json().await?), + status => Err(Error::Http(status, response)), + } } } @@ -342,23 +330,20 @@ impl Databases { json }; - if let Some(json) = json { + if let Some(ref json) = json { request = request - .body_json(&json) + .body_json(json) .expect("to parse JSON for start_cursor"); } - let mut response = (self.request_handler)(&mut request).await?; + log::trace!("Querying database with request: {request:#?} and body: {json:#?}"); - Ok(response.body_json().await?) + let mut response = (self.request_handler)(request).await?; - // match response.error_for_status_ref() { - // Ok(_) => try_to_parse_response(response).await, - // Err(error) => { - // let body = try_to_parse_response::(response).await?; - // Err(Error::Http(error, Some(body))) - // } - // } + match response.status() { + StatusCode::Ok => Ok(response.body_json().await?), + status => Err(Error::Http(status, response)), + } } } @@ -423,18 +408,14 @@ impl Users { pub async fn get(&self) -> Result> { let url = "https://api.notion.com/v1/users".to_owned(); - let mut request = self.http_client.get(&url); + let request = self.http_client.get(&url); - let mut response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(request).await?; - Ok(response.body_json().await?) - // match response.error_for_status_ref() { - // Ok(_) => Ok(response.json().await?), - // Err(error) => { - // let body = response.json::().await?; - // Err(Error::Http(error, Some(body))) - // } - // } + match response.status() { + StatusCode::Ok => Ok(response.body_json().await?), + status => Err(Error::Http(status, response)), + } } } @@ -978,7 +959,7 @@ pub struct Relation { // TODO: Paginate all possible responses #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct QueryResponse { - pub has_more: bool, + pub has_more: Option, pub next_cursor: Option, pub results: Vec, }