use crate::backend::{HttpRequest, HttpResponse, HttpStreamingResponse};
use crate::Error;
use super::{
BoxHttpService, BoxStreamingHttpService, ReqwestHttpService, ReqwestStreamingHttpService,
};
pub use tower::limit::{ConcurrencyLimitLayer, RateLimitLayer};
pub use tower::timeout::TimeoutLayer;
pub use tower::ServiceBuilder;
pub fn reqwest_service(client: reqwest::Client) -> ReqwestHttpService {
ReqwestHttpService::new(client)
}
pub fn build<F>(client: reqwest::Client, configure: F) -> BoxHttpService
where
F: FnOnce(ReqwestHttpService) -> BoxHttpService,
{
configure(ReqwestHttpService::new(client))
}
pub fn build_dual<F>(
client: reqwest::Client,
configure: F,
) -> (BoxHttpService, BoxStreamingHttpService)
where
F: FnOnce(
ReqwestHttpService,
ReqwestStreamingHttpService,
) -> (BoxHttpService, BoxStreamingHttpService),
{
configure(
ReqwestHttpService::new(client.clone()),
ReqwestStreamingHttpService::new(client),
)
}
pub trait IntoBoxHttpService: Sized {
fn into_box(self) -> BoxHttpService;
}
impl<S> IntoBoxHttpService for S
where
S: tower::Service<HttpRequest, Response = HttpResponse, Error = Error> + Clone + Send + 'static,
S::Future: Send + 'static,
{
fn into_box(self) -> BoxHttpService {
BoxHttpService::new(self)
}
}
pub trait IntoBoxStreamingHttpService: Sized {
fn into_streaming_box(self) -> BoxStreamingHttpService;
}
impl<S> IntoBoxStreamingHttpService for S
where
S: tower::Service<HttpRequest, Response = HttpStreamingResponse, Error = Error>
+ Clone
+ Send
+ 'static,
S::Future: Send + 'static,
{
fn into_streaming_box(self) -> BoxStreamingHttpService {
BoxStreamingHttpService::new(self)
}
}
pub fn with_concurrency_limit(client: reqwest::Client, max_in_flight: usize) -> BoxHttpService {
build(client, |inner| {
ServiceBuilder::new()
.layer(ConcurrencyLimitLayer::new(max_in_flight))
.service(inner)
.into_box()
})
}
pub fn with_buffer(client: reqwest::Client, capacity: usize) -> BoxHttpService {
build(client, |inner| {
let buffered = tower::buffer::Buffer::new(inner, capacity);
ServiceBuilder::new()
.map_err(|e: tower::BoxError| Error::transport_message(e.to_string()))
.service(buffered)
.into_box()
})
}
pub fn with_request_logging(client: reqwest::Client) -> BoxHttpService {
build(client, |inner| {
ServiceBuilder::new()
.map_request(|req: HttpRequest| {
tracing::debug!(method = %req.method, url = %req.url, "better-fetch transport");
req
})
.service(inner)
.into_box()
})
}