I'm trying to create a wrapper around reqwest::Client
. I created the " InterServiceClient " trait and implemented it using the "InterServiceClientImpl" struct. One of the "InterServiceClient" methods looks like below.
async fn post<R: DeserializeOwned + Send + Sync>(
&self,
url: &str,
headers: Vec<Header>,
) -> Result<R, reqwest::Error>;
and I wrote a method to get the InterServiceClient.
pub fn build_interservice(base_url: String) -> Box<dyn InterServiceClient> {
Box::new(InterServiceClientImpl::build(base_url))
}
But I'm getting the below error from the above method.
the trait
InterServiceClient
cannot be made into an object
consider movingpost
to another trait
only typeutils::interservice::InterServiceClientImpl
is seen to implement the trait in this crate, consider using it directly instead
InterServiceClient
can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
required for the cast fromBox<InterServiceClientImpl>
toBox<(dyn InterServiceClient + 'static)>
Need help to solve this issue.
Update
This is my code looks like
pub fn build_interservice(base_url: String) -> Box<dyn InterServiceClient> {
Box::new(InterServiceClientImpl::build(base_url))
}
#[async_trait]
pub trait InterServiceClient: InterServiceClientClone + Send {
async fn post<R: DeserializeOwned + Send + Sync>(
&self,
url: &str,
headers: Vec<Header>,
) -> Result<R, reqwest::Error>;
}
#[derive(Clone)]
struct InterServiceClientImpl {
client: reqwest::Client,
base_url: String,
}
impl Clone for Box<dyn InterServiceClient> {
fn clone(&self) -> Box<dyn InterServiceClient> {
self.clone_box()
}
}
pub trait InterServiceClientClone {
fn clone_box(&self) -> Box<dyn InterServiceClient + Send + Sync>;
}
impl InterServiceClientClone for InterServiceClientImpl {
fn clone_box(&self) -> Box<dyn InterServiceClient + Send + Sync> {
Box::new(self.clone())
}
}
#[derive(Debug, Clone)]
pub struct Header {
header: String,
value: String,
}
impl Header {
pub fn build(header: String, value: String) -> Self {
Header { header, value }
}
}
impl InterServiceClientImpl {
pub fn build(base_url: String) -> Self {
let client: reqwest::Client = reqwest::Client::new();
InterServiceClientImpl { client, base_url }
}
}
#[async_trait]
impl InterServiceClient for InterServiceClientImpl {
async fn post<R: DeserializeOwned + Send + Sync >(
&self,
url: &str,
headers: Vec<Header>,
) -> Result<R, reqwest::Error> {
let builder = self
.client
.post(format!("{}/{}", self.base_url, url))
// .json(body)
.header("Content-Type", "application/json");
let builder = headers.iter().fold(builder, |builder, header| {
builder.header(&header.header, &header.value)
});
let result = builder.send().await;
match result {
Ok(response) => {
debug!("Response from server : {:?}", response);
let result = response.json::<R>().await?;
Ok(result)
}
Err(error) => {
error!("Error invoking api {:?}", error);
Err(error)
}
}
}
}