From a4372e01890537695932f5c9042a8e884a810d23 Mon Sep 17 00:00:00 2001 From: Adam Chalmers Date: Thu, 9 Jan 2020 12:13:04 -0600 Subject: [PATCH] Trait for async API clients. Mock now implements the async API client trait too. --- cloudflare-e2e-test/src/main.rs | 16 ++++++++--- cloudflare/Cargo.toml | 1 + cloudflare/src/framework/apiclient.rs | 1 + cloudflare/src/framework/async_api.rs | 22 +++++++++++++--- cloudflare/src/framework/mock.rs | 38 +++++++++++++++++++-------- 5 files changed, 59 insertions(+), 19 deletions(-) diff --git a/cloudflare-e2e-test/src/main.rs b/cloudflare-e2e-test/src/main.rs index fc4f6c1c..adff5118 100644 --- a/cloudflare-e2e-test/src/main.rs +++ b/cloudflare-e2e-test/src/main.rs @@ -1,16 +1,24 @@ use clap::{App, AppSettings, Arg}; -use cloudflare::framework::{async_api, auth::Credentials, Environment, HttpApiClientConfig}; +use cloudflare::framework::{ + async_api, async_api::ApiClient, auth::Credentials, Environment, HttpApiClientConfig, +}; use failure::{Error, Fallible}; use std::fmt::Display; use std::net::{IpAddr, Ipv4Addr}; -async fn tests(api_client: &async_api::Client, account_id: &str) -> Fallible<()> { - test_lb_pool(&api_client, &account_id).await?; +async fn tests( + api_client: &ApiClientType, + account_id: &str, +) -> Fallible<()> { + test_lb_pool(api_client, &account_id).await?; println!("Tests passed"); Ok(()) } -async fn test_lb_pool(api_client: &async_api::Client, account_identifier: &str) -> Fallible<()> { +async fn test_lb_pool( + api_client: &ApiClientType, + account_identifier: &str, +) -> Fallible<()> { use cloudflare::endpoints::load_balancing::*; // Create a pool diff --git a/cloudflare/Cargo.toml b/cloudflare/Cargo.toml index ada1c989..e8d5e7f4 100644 --- a/cloudflare/Cargo.toml +++ b/cloudflare/Cargo.toml @@ -9,6 +9,7 @@ categories = ["api-bindings", "web-programming::http-client"] license = "BSD-3-Clause" [dependencies] +async-trait = "0.1.22" chrono = { version = "0.4", features = ["serde"] } http = "0.1.18" reqwest = { version = "0.10", features = ["json", "blocking"] } diff --git a/cloudflare/src/framework/apiclient.rs b/cloudflare/src/framework/apiclient.rs index abb4db04..654b5183 100644 --- a/cloudflare/src/framework/apiclient.rs +++ b/cloudflare/src/framework/apiclient.rs @@ -1,3 +1,4 @@ +//! This module contains the synchronous (blocking) API client. use crate::framework::{ endpoint::Endpoint, response::{ApiResponse, ApiResult}, diff --git a/cloudflare/src/framework/async_api.rs b/cloudflare/src/framework/async_api.rs index d3789038..beb01462 100644 --- a/cloudflare/src/framework/async_api.rs +++ b/cloudflare/src/framework/async_api.rs @@ -7,9 +7,22 @@ use crate::framework::{ response::{ApiResponse, ApiResult}, Environment, HttpApiClientConfig, }; +use async_trait::async_trait; use reqwest; use serde::Serialize; +#[async_trait] +pub trait ApiClient { + async fn request( + &self, + endpoint: &(dyn Endpoint + Send + Sync), + ) -> ApiResponse + where + ResultType: ApiResult, + QueryType: Serialize, + BodyType: Serialize; +} + /// A Cloudflare API client that makes requests asynchronously. pub struct Client { environment: Environment, @@ -42,12 +55,13 @@ impl Client { http_client, }) } +} - // Currently, futures/async fns aren't supported in traits, and won't be for a while. - // So unlike ApiClient/HttpApiClient, there's no trait with the request method. - pub async fn request( +#[async_trait] +impl ApiClient for Client { + async fn request( &self, - endpoint: &dyn Endpoint, + endpoint: &(dyn Endpoint + Send + Sync), ) -> ApiResponse where ResultType: ApiResult, diff --git a/cloudflare/src/framework/mock.rs b/cloudflare/src/framework/mock.rs index dd68217e..9192f215 100644 --- a/cloudflare/src/framework/mock.rs +++ b/cloudflare/src/framework/mock.rs @@ -1,6 +1,8 @@ use crate::framework::apiclient::ApiClient; +use crate::framework::async_api; use crate::framework::endpoint::{Endpoint, Method}; use crate::framework::response::{ApiError, ApiErrors, ApiFailure, ApiResponse, ApiResult}; +use async_trait::async_trait; use reqwest; use std::collections::HashMap; @@ -22,21 +24,35 @@ impl Endpoint for NoopEndpoint { pub struct NoopResult {} impl ApiResult for NoopResult {} +fn mock_response() -> ApiFailure { + ApiFailure::Error( + reqwest::StatusCode::INTERNAL_SERVER_ERROR, + ApiErrors { + errors: vec![ApiError { + code: 9999, + message: "This is a mocked failure response".to_owned(), + other: HashMap::new(), + }], + other: HashMap::new(), + }, + ) +} + impl ApiClient for MockApiClient { fn request( &self, _endpoint: &dyn Endpoint, ) -> ApiResponse { - Err(ApiFailure::Error( - reqwest::StatusCode::INTERNAL_SERVER_ERROR, - ApiErrors { - errors: vec![ApiError { - code: 9999, - message: "This is a mocked failure response".to_owned(), - other: HashMap::new(), - }], - other: HashMap::new(), - }, - )) + Err(mock_response()) + } +} + +#[async_trait] +impl async_api::ApiClient for MockApiClient { + async fn request( + &self, + _endpoint: &(dyn Endpoint + Send + Sync), + ) -> ApiResponse { + Err(mock_response()) } }