use std::task::{Context, Poll};
use http::HeaderValue;
use http::header::USER_AGENT;
use tower::{Layer, Service};
pub fn default_user_agent() -> HeaderValue {
let pkg = env!("CARGO_PKG_VERSION");
let sha = env!("DEFECT_HTTP_GIT_SHA");
let raw = format!("defect-http/{pkg} ({sha})");
HeaderValue::from_str(&raw).unwrap_or_else(|_| HeaderValue::from_static("defect-http"))
}
#[derive(Debug, Clone)]
pub(crate) struct UserAgentLayer {
value: HeaderValue,
}
impl UserAgentLayer {
pub(crate) fn new(value: HeaderValue) -> Self {
Self { value }
}
}
impl<S> Layer<S> for UserAgentLayer {
type Service = UserAgent<S>;
fn layer(&self, inner: S) -> Self::Service {
UserAgent {
inner,
value: self.value.clone(),
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct UserAgent<S> {
inner: S,
value: HeaderValue,
}
impl<S, B> Service<http::Request<B>> for UserAgent<S>
where
S: Service<http::Request<B>>,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, mut req: http::Request<B>) -> Self::Future {
req.headers_mut()
.entry(USER_AGENT)
.or_insert_with(|| self.value.clone());
self.inner.call(req)
}
}
#[cfg(test)]
mod tests;