rustify/client.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
//! Contains the [Client] trait for executing
//! [Endpoints][crate::endpoint::Endpoint].
use crate::errors::ClientError;
use async_trait::async_trait;
use http::{Request, Response};
use std::ops::RangeInclusive;
/// An array of HTTP response codes which indicate a successful response
pub const HTTP_SUCCESS_CODES: RangeInclusive<u16> = 200..=208;
/// Represents an HTTP client which is capable of executing
/// [Endpoints][crate::endpoint::Endpoint] by sending the [Request] generated
/// by the Endpoint and returning a [Response].
#[async_trait]
pub trait Client: Sync + Send {
/// Sends the given [Request] and returns a [Response]. Implementations
/// should consolidate all errors into the [ClientError] type.
async fn send(&self, req: Request<Vec<u8>>) -> Result<Response<Vec<u8>>, ClientError>;
/// Returns the base URL the client is configured with. This is used for
/// creating the fully qualified URLs used when executing
/// [Endpoints][crate::endpoint::Endpoint].
fn base(&self) -> &str;
/// This method provides a common interface to
/// [Endpoints][crate::endpoint::Endpoint] for execution.
// TODO: remove the allow when the upstream clippy issue is fixed:
// <https://github.com/rust-lang/rust-clippy/issues/12281>
#[allow(clippy::blocks_in_conditions)]
#[instrument(skip(self, req), err)]
async fn execute(&self, req: Request<Vec<u8>>) -> Result<Response<Vec<u8>>, ClientError> {
debug!(
"Client sending {} request to {} with {} bytes of data",
req.method().to_string(),
req.uri(),
req.body().len(),
);
let response = self.send(req).await?;
debug!(
"Client received {} response with {} bytes of body data",
response.status().as_u16(),
response.body().len()
);
// Check response
if !HTTP_SUCCESS_CODES.contains(&response.status().as_u16()) {
return Err(ClientError::ServerResponseError {
code: response.status().as_u16(),
content: String::from_utf8(response.body().to_vec()).ok(),
});
}
// Parse response content
Ok(response)
}
}