use crate::service::{Layer, Service};
use crate::{builder, Agent, Builder, UserAgent};
use conjure_http::client::Endpoint;
use http::header::USER_AGENT;
use http::{HeaderValue, Request};
use std::convert::TryFrom;
use std::future::Future;
pub struct UserAgentLayer {
user_agent: UserAgent,
}
impl UserAgentLayer {
pub fn new(builder: &Builder<builder::Complete>) -> UserAgentLayer {
UserAgentLayer {
user_agent: builder.get_user_agent().clone(),
}
}
}
impl<S> Layer<S> for UserAgentLayer {
type Service = UserAgentService<S>;
fn layer(self, inner: S) -> Self::Service {
UserAgentService {
inner,
user_agent: self.user_agent,
}
}
}
pub struct UserAgentService<S> {
inner: S,
user_agent: UserAgent,
}
impl<S, B> Service<Request<B>> for UserAgentService<S>
where
S: Service<Request<B>>,
{
type Response = S::Response;
type Error = S::Error;
fn call(
&self,
mut req: Request<B>,
) -> impl Future<Output = Result<Self::Response, Self::Error>> {
let endpoint = req
.extensions()
.get::<Endpoint>()
.expect("Endpoint missing from request extensions");
let mut user_agent = self.user_agent.clone();
user_agent.push_agent(Agent::new(
endpoint.service(),
endpoint.version().unwrap_or("0.0.0"),
));
user_agent.push_agent(Agent::new(
"conjure-rust-runtime",
env!("CARGO_PKG_VERSION"),
));
let user_agent = user_agent.to_string();
req.headers_mut()
.insert(USER_AGENT, HeaderValue::try_from(user_agent).unwrap());
self.inner.call(req)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::service;
use crate::user_agent::Agent;
use http::HeaderMap;
#[tokio::test]
async fn basic() {
let layer = UserAgentLayer::new(
&Builder::new()
.service("foo")
.user_agent(UserAgent::new(Agent::new("foobar", "1.0.0"))),
);
let service = layer.layer(service::service_fn(|req| async { Ok::<_, ()>(req) }));
let request = Request::builder()
.extension(Endpoint::new(
"serviceName",
Some("2.3.4"),
"endpoint",
"/path",
))
.body(())
.unwrap();
let out = service.call(request).await.unwrap();
let mut headers = HeaderMap::new();
headers.insert(
USER_AGENT,
HeaderValue::from_static(concat!(
"foobar/1.0.0 serviceName/2.3.4 conjure-rust-runtime/",
env!("CARGO_PKG_VERSION")
)),
);
assert_eq!(*out.headers(), headers);
}
}