diff --git a/src/api/oauth.rs b/src/api/oauth.rs index 3fde2eb..64c0bfc 100644 --- a/src/api/oauth.rs +++ b/src/api/oauth.rs @@ -25,7 +25,9 @@ where req: &SlackOAuthV2AccessTokenRequest, ) -> ClientResult { let full_uri: Url = SlackClientHttpApiUri::create_url_with_params( - &SlackClientHttpApiUri::create_method_uri_path("oauth.v2.access"), + self.http_api + .connector + .create_method_uri_path("oauth.v2.access")?, &vec![ ("code", Some(req.code.value())), ( @@ -36,7 +38,7 @@ where .as_ref(), ), ], - ); + )?; self.http_api .connector diff --git a/src/api/test.rs b/src/api/test.rs index 4e2127a..1718bea 100644 --- a/src/api/test.rs +++ b/src/api/test.rs @@ -19,9 +19,13 @@ where /// pub async fn api_test(&self, req: &SlackApiTestRequest) -> ClientResult { let full_uri = SlackClientHttpApiUri::create_url_with_params( - &SlackClientHttpApiUri::create_method_uri_path("api.test"), + self.http_session_api + .client + .http_api + .connector + .create_method_uri_path("api.test")?, &vec![("foo", req.foo.as_ref()), ("error", req.error.as_ref())], - ); + )?; self.http_session_api .http_post_uri(full_uri, &req, Some(&SLACK_TIER4_METHOD_CONFIG)) .await diff --git a/src/axum_support/slack_oauth_routes.rs b/src/axum_support/slack_oauth_routes.rs index f73a2be..5ac98ac 100644 --- a/src/axum_support/slack_oauth_routes.rs +++ b/src/axum_support/slack_oauth_routes.rs @@ -30,7 +30,7 @@ impl SlackEventsAxumListener { let environment = environment.clone(); async move { let full_uri = SlackClientHttpApiUri::create_url_with_params( - SlackOAuthListenerConfig::OAUTH_AUTHORIZE_URL_VALUE, + SlackOAuthListenerConfig::OAUTH_AUTHORIZE_URL_VALUE.parse()?, &vec![ ("client_id", Some(config.client_id.value())), ("scope", Some(&config.bot_scope)), @@ -39,7 +39,7 @@ impl SlackEventsAxumListener { Some(config.to_redirect_url()?.as_str().to_string()).as_ref(), ), ], - ); + )?; debug!("Redirecting to Slack OAuth authorize: {}", &full_uri); HyperExtensions::hyper_redirect_to(full_uri.as_ref()).map(|r| r.into_response()) } diff --git a/src/client.rs b/src/client.rs index 3f39a13..14a75d8 100644 --- a/src/client.rs +++ b/src/client.rs @@ -8,7 +8,8 @@ use crate::errors::SlackClientError; use crate::models::*; use crate::multipart_form::FileMultipartData; use crate::ratectl::SlackApiMethodRateControlConfig; -use futures_util::future::BoxFuture; +use futures::future::BoxFuture; +use futures::FutureExt; use lazy_static::*; use rvstruct::ValueStruct; use tracing::*; @@ -43,7 +44,7 @@ pub struct SlackClientHttpSessionApi<'a, SCHC> where SCHC: SlackClientHttpConnector + Send, { - client: &'a SlackClient, + pub client: &'a SlackClient, token: &'a SlackApiToken, pub span: Span, } @@ -85,12 +86,14 @@ pub trait SlackClientHttpConnector { PT: std::iter::IntoIterator)> + Clone, TS: AsRef + 'p + Send, { - let full_uri = SlackClientHttpApiUri::create_url_with_params( - &SlackClientHttpApiUri::create_method_uri_path(method_relative_uri), - params, - ); + let full_uri = self + .create_method_uri_path(method_relative_uri) + .and_then(|url| SlackClientHttpApiUri::create_url_with_params(url, params)); - self.http_get_uri(full_uri, context) + match full_uri { + Ok(full_uri) => self.http_get_uri(full_uri, context), + Err(err) => std::future::ready(Err(err)).boxed(), + } } fn http_post_uri<'a, RQ, RS>( @@ -113,11 +116,10 @@ pub trait SlackClientHttpConnector { RQ: serde::ser::Serialize + Send + Sync, RS: for<'de> serde::de::Deserialize<'de> + Send + 'a, { - let full_uri = SlackClientHttpApiUri::create_url( - &SlackClientHttpApiUri::create_method_uri_path(method_relative_uri), - ); - - self.http_post_uri(full_uri, request, context) + match self.create_method_uri_path(method_relative_uri) { + Ok(full_uri) => self.http_post_uri(full_uri, request, context), + Err(err) => std::future::ready(Err(err)).boxed(), + } } fn http_post_uri_multipart_form<'a, 'p, RS, PT, TS>( @@ -144,11 +146,14 @@ pub trait SlackClientHttpConnector { PT: std::iter::IntoIterator)> + Clone, TS: AsRef + 'p + Send, { - let full_uri = SlackClientHttpApiUri::create_url( - &SlackClientHttpApiUri::create_method_uri_path(method_relative_uri), - ); + match self.create_method_uri_path(method_relative_uri) { + Ok(full_uri) => self.http_post_uri_multipart_form(full_uri, file, params, context), + Err(err) => std::future::ready(Err(err)).boxed(), + } + } - self.http_post_uri_multipart_form(full_uri, file, params, context) + fn create_method_uri_path(&self, method_relative_uri: &str) -> ClientResult { + Ok(SlackClientHttpApiUri::create_method_uri_path(method_relative_uri).parse()?) } } @@ -188,17 +193,13 @@ where pub struct SlackClientHttpApiUri; impl SlackClientHttpApiUri { - const SLACK_API_URI_STR: &'static str = "https://slack.com/api"; + pub const SLACK_API_URI_STR: &'static str = "https://slack.com/api"; pub fn create_method_uri_path(method_relative_uri: &str) -> String { format!("{}/{}", Self::SLACK_API_URI_STR, method_relative_uri) } - pub(crate) fn create_url(url_str: &str) -> Url { - url_str.parse().unwrap() - } - - pub fn create_url_with_params<'p, PT, TS>(url_str: &str, params: &'p PT) -> Url + pub fn create_url_with_params<'p, PT, TS>(base_url: Url, params: &'p PT) -> ClientResult where PT: std::iter::IntoIterator)> + Clone, TS: AsRef + 'p, @@ -209,11 +210,7 @@ impl SlackClientHttpApiUri { .filter_map(|(k, vo)| vo.map(|v| (k.to_string(), v.as_ref().to_string()))) .collect(); - Url::parse_with_params(url_str, url_query_params) - .unwrap() - .as_str() - .parse() - .unwrap() + Ok(Url::parse_with_params(base_url.as_str(), url_query_params)?) } } diff --git a/src/hyper_tokio/connector.rs b/src/hyper_tokio/connector.rs index 01f6a2d..7fccfac 100644 --- a/src/hyper_tokio/connector.rs +++ b/src/hyper_tokio/connector.rs @@ -30,6 +30,7 @@ use url::Url; pub struct SlackClientHyperConnector { hyper_connector: Client, tokio_rate_controller: Option>, + slack_api_url: String, } pub type SlackClientHyperHttpsConnector = @@ -59,6 +60,7 @@ impl SlackClientHyperConnec Self { hyper_connector: Client::builder(TokioExecutor::new()).build::<_, Body>(connector), tokio_rate_controller: None, + slack_api_url: SlackClientHttpApiUri::SLACK_API_URI_STR.to_string(), } } @@ -71,6 +73,13 @@ impl SlackClientHyperConnec } } + pub fn with_slack_api_url(self, slack_api_url: &str) -> Self { + Self { + slack_api_url: slack_api_url.to_string(), + ..self + } + } + async fn send_http_request<'a, RS>( &'a self, request: Request, @@ -267,6 +276,10 @@ impl SlackClientHyperConnec impl SlackClientHttpConnector for SlackClientHyperConnector { + fn create_method_uri_path(&self, method_relative_uri: &str) -> ClientResult { + Ok(format!("{}/{}", self.slack_api_url, method_relative_uri).parse()?) + } + fn http_get_uri<'a, RS>( &'a self, full_uri: Url, diff --git a/src/hyper_tokio/listener/oauth.rs b/src/hyper_tokio/listener/oauth.rs index f65e555..b9f89f4 100644 --- a/src/hyper_tokio/listener/oauth.rs +++ b/src/hyper_tokio/listener/oauth.rs @@ -22,7 +22,7 @@ impl SlackClientEventsHyperListener< config: &SlackOAuthListenerConfig, ) -> AnyStdResult> { let full_uri = SlackClientHttpApiUri::create_url_with_params( - SlackOAuthListenerConfig::OAUTH_AUTHORIZE_URL_VALUE, + SlackOAuthListenerConfig::OAUTH_AUTHORIZE_URL_VALUE.parse()?, &vec![ ("client_id", Some(config.client_id.value())), ("scope", Some(&config.bot_scope)), @@ -31,7 +31,7 @@ impl SlackClientEventsHyperListener< Some(config.to_redirect_url()?.as_str().to_string()).as_ref(), ), ], - ); + )?; debug!("Redirecting to Slack OAuth authorize: {}", &full_uri); HyperExtensions::hyper_redirect_to(full_uri.as_ref()) }