From 83cc5e85fc1807e3511bf04d1d30e83002a31585 Mon Sep 17 00:00:00 2001 From: Bram Dingelstad Date: Thu, 21 Mar 2024 22:23:05 +0100 Subject: [PATCH] wip: started replacing reqwest with surf --- Cargo.toml | 3 +- src/lib.rs | 191 +++++++++++++++++++++++++---------------------------- 2 files changed, 93 insertions(+), 101 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 53423ea..79b7b82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ request = [] convert_from_notion = [] [dependencies] +async-std = "1.12.0" async-trait = "0.1.68" base64 = "0.21.0" chrono = "0.4.31" @@ -16,9 +17,9 @@ futures-core = "0.3.28" lazy_static = "1.4.0" log = "0.4.20" regex = "1.7.1" -reqwest = { version = "0.11.14", features = ["json"] } serde = { version = "^1.0", features = ["derive"], default-features = false } serde_json = { version = "^1.0", features = ["raw_value"], default-features = false } +surf = "2.3.2" [dev-dependencies] tokio = { version = "1.28.1", features = ["macros"] } diff --git a/src/lib.rs b/src/lib.rs index eb21077..7a8368e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,6 @@ use std::sync::Arc; use chrono::{DateTime, NaiveTime, Utc}; use lazy_static::lazy_static; use regex::Regex; -#[cfg(feature = "request")] -use reqwest::header::{HeaderMap, HeaderValue}; use serde::de::Error as SerdeError; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::json; @@ -22,18 +20,15 @@ lazy_static! { const NOTION_VERSION: &str = "2022-06-28"; pub type Result = std::result::Result; -pub type Callback = dyn Fn( - &mut reqwest::RequestBuilder, - ) -> BoxFuture<'_, std::result::Result> +pub type Callback = dyn Fn(&mut surf::RequestBuilder) -> BoxFuture<'_, std::result::Result> + 'static + Send + Sync; #[derive(Debug)] pub enum Error { - Http(reqwest::Error, Option), + Http(surf::Error, Option), Deserialization(serde_json::Error, Option), - Header(reqwest::header::InvalidHeaderValue), ChronoParse(chrono::ParseError), UnexpectedType, } @@ -44,18 +39,12 @@ impl std::fmt::Display for Error { } } -impl From for Error { - fn from(error: reqwest::Error) -> Self { +impl From for Error { + fn from(error: surf::Error) -> Self { Error::Http(error, None) } } -impl From for Error { - fn from(error: reqwest::header::InvalidHeaderValue) -> Self { - Error::Header(error) - } -} - impl From for Error { fn from(error: serde_json::Error) -> Self { Error::Deserialization(error, None) @@ -68,37 +57,30 @@ impl From for Error { } } -async fn try_to_parse_response serde::Deserialize<'de>>( - response: reqwest::Response, -) -> Result { - let text = response.text().await?; +// async fn try_to_parse_response serde::Deserialize<'de>>( +// mut response: surf::Response, +// ) -> Result { +// let text = response.body_string().await?; - match serde_json::from_str::(&text) { - Ok(value) => Ok(value), - Err(error) => match serde_json::from_str::(&text) { - Ok(body) => Err(Error::Deserialization(error, Some(body))), - _ => Err(Error::Deserialization(error, Some(Value::String(text)))), - }, - } -} +// match serde_json::from_str::(&text) { +// Ok(value) => Ok(value), +// Err(error) => match serde_json::from_str::(&text) { +// Ok(body) => Err(Error::Deserialization(error, Some(body))), +// _ => Err(Error::Deserialization(error, Some(Value::String(text)))), +// }, +// } +// } #[cfg(feature = "request")] -fn get_http_client(notion_api_key: &str) -> reqwest::Client { - let mut headers = HeaderMap::new(); - headers.insert( - "Authorization", - HeaderValue::from_str(&format!("Bearer {notion_api_key}")) - .expect("bearer token to be parsed into a header"), - ); - headers.insert( - "Notion-Version", - HeaderValue::from_str(NOTION_VERSION).expect("notion version to be parsed into a header"), - ); - headers.insert("Content-Type", HeaderValue::from_static("application/json")); - - reqwest::ClientBuilder::new() - .default_headers(headers) - .build() +fn get_http_client(notion_api_key: &str) -> surf::Client { + surf::Config::new() + .add_header("Authorization", format!("Bearer {notion_api_key}")) + .unwrap() + .add_header("Notion-Version", NOTION_VERSION) + .unwrap() + .add_header("Content-Type", "application/json") + .unwrap() + .try_into() .expect("to build a valid client out of notion_api_key") } @@ -132,8 +114,8 @@ impl ClientBuilder { pub fn custom_request(mut self, callback: F) -> Self where for<'c> F: Fn( - &'c mut reqwest::RequestBuilder, - ) -> BoxFuture<'c, std::result::Result> + &'c mut surf::RequestBuilder, + ) -> BoxFuture<'c, std::result::Result> + 'static + Send + Sync, @@ -148,13 +130,13 @@ impl ClientBuilder { 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 reqwest::RequestBuilder| { + |request_builder: &mut surf::RequestBuilder| { Box::pin(async move { - let request = request_builder - .try_clone() - .expect("non-stream body request clone to succeed"); + // let request = request_builder + // .clone() + // .expect("non-stream body request clone to succeed"); - request.send().await + request_builder.await }) }, )); @@ -186,7 +168,7 @@ impl ClientBuilder { } pub struct Client { - http_client: Arc, + http_client: Arc, request_handler: Arc, pub pages: Pages, @@ -207,17 +189,20 @@ impl<'a> Client { let mut request = self .http_client .post("https://api.notion.com/v1/search") - .json(&options); + .body_json(&options) + .unwrap(); - let response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(&mut request).await.unwrap(); - match response.error_for_status_ref() { - Ok(_) => Ok(response.json().await?), - Err(error) => { - let body = response.json::().await?; - Err(Error::Http(error, Some(body))) - } - } + 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))) + // } + // } } } @@ -227,7 +212,7 @@ pub struct PageOptions<'a> { #[derive(Clone)] pub struct Pages { - http_client: Arc, + http_client: Arc, request_handler: Arc, } @@ -240,21 +225,22 @@ impl Pages { let mut request = self.http_client.get(url); - let response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(&mut request).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))) - } - } + 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))) + // } + // } } } #[derive(Clone)] pub struct Blocks { - http_client: Arc, + http_client: Arc, request_handler: Arc, } @@ -268,7 +254,7 @@ impl Blocks { } pub struct BlockChildren { - http_client: Arc, + http_client: Arc, request_handler: Arc, } @@ -288,21 +274,23 @@ impl BlockChildren { let mut request = self.http_client.get(&url); - let response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(&mut request).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))) - } - } + 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))) + // } + // } } } #[derive(Clone)] pub struct Databases { - http_client: Arc, + http_client: Arc, request_handler: Arc, } @@ -353,18 +341,20 @@ impl Databases { }; if let Some(json) = json { - request = request.json(&json); + request = request.body_json(&json).unwrap(); } - let response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(&mut 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))) - } - } + Ok(response.body_json().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))) + // } + // } } } @@ -372,7 +362,7 @@ impl Databases { mod tests { use super::*; - #[tokio::test] + #[async_std::test] async fn check_database_query() { let databases = Client::new() .api_key("secret_FuhJkAoOVZlk8YUT9ZOeYqWBRRZN6OMISJwhb4dTnud") @@ -394,7 +384,7 @@ mod tests { println!("{databases:#?}"); } - #[tokio::test] + #[async_std::test] async fn test_blocks() { let blocks = Client::new() .api_key("secret_FuhJkAoOVZlk8YUT9ZOeYqWBRRZN6OMISJwhb4dTnud") @@ -421,7 +411,7 @@ pub struct DatabaseQueryOptions<'a> { #[derive(Clone)] pub struct Users { - http_client: Arc, + http_client: Arc, request_handler: Arc, } @@ -431,15 +421,16 @@ impl Users { let mut request = self.http_client.get(&url); - let response = (self.request_handler)(&mut request).await?; + let mut response = (self.request_handler)(&mut request).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))) - } - } + 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))) + // } + // } } }