better_fetch/tower/
stack.rs1use crate::backend::{HttpRequest, HttpResponse};
4use crate::Error;
5
6use super::{BoxHttpService, ReqwestHttpService};
7
8pub use tower::limit::{ConcurrencyLimitLayer, RateLimitLayer};
9pub use tower::timeout::TimeoutLayer;
10pub use tower::ServiceBuilder;
11
12pub fn reqwest_service(client: reqwest::Client) -> ReqwestHttpService {
14 ReqwestHttpService::new(client)
15}
16
17pub fn build<F>(client: reqwest::Client, configure: F) -> BoxHttpService
22where
23 F: FnOnce(ReqwestHttpService) -> BoxHttpService,
24{
25 configure(ReqwestHttpService::new(client))
26}
27
28pub trait IntoBoxHttpService: Sized {
30 fn into_box(self) -> BoxHttpService;
32}
33
34impl<S> IntoBoxHttpService for S
35where
36 S: tower::Service<HttpRequest, Response = HttpResponse, Error = Error> + Clone + Send + 'static,
37 S::Future: Send + 'static,
38{
39 fn into_box(self) -> BoxHttpService {
40 BoxHttpService::new(self)
41 }
42}
43
44pub fn with_concurrency_limit(client: reqwest::Client, max_in_flight: usize) -> BoxHttpService {
46 build(client, |inner| {
47 ServiceBuilder::new()
48 .layer(ConcurrencyLimitLayer::new(max_in_flight))
49 .service(inner)
50 .into_box()
51 })
52}
53
54pub fn with_buffer(client: reqwest::Client, capacity: usize) -> BoxHttpService {
61 build(client, |inner| {
62 let buffered = tower::buffer::Buffer::new(inner, capacity);
63 ServiceBuilder::new()
64 .map_err(|e: tower::BoxError| Error::transport_message(e.to_string()))
65 .service(buffered)
66 .into_box()
67 })
68}
69
70pub fn with_request_logging(client: reqwest::Client) -> BoxHttpService {
72 build(client, |inner| {
73 ServiceBuilder::new()
74 .map_request(|req: HttpRequest| {
75 tracing::debug!(method = %req.method, url = %req.url, "better-fetch transport");
76 req
77 })
78 .service(inner)
79 .into_box()
80 })
81}