better_fetch/tower/
stack.rs1use crate::backend::{HttpRequest, HttpResponse, HttpStreamingResponse};
4use crate::Error;
5
6use super::{
7 BoxHttpService, BoxStreamingHttpService, ReqwestHttpService, ReqwestStreamingHttpService,
8};
9
10pub use tower::limit::{ConcurrencyLimitLayer, RateLimitLayer};
11pub use tower::timeout::TimeoutLayer;
12pub use tower::ServiceBuilder;
13
14pub fn reqwest_service(client: reqwest::Client) -> ReqwestHttpService {
16 ReqwestHttpService::new(client)
17}
18
19pub fn build<F>(client: reqwest::Client, configure: F) -> BoxHttpService
24where
25 F: FnOnce(ReqwestHttpService) -> BoxHttpService,
26{
27 configure(ReqwestHttpService::new(client))
28}
29
30pub fn build_dual<F>(
32 client: reqwest::Client,
33 configure: F,
34) -> (BoxHttpService, BoxStreamingHttpService)
35where
36 F: FnOnce(
37 ReqwestHttpService,
38 ReqwestStreamingHttpService,
39 ) -> (BoxHttpService, BoxStreamingHttpService),
40{
41 configure(
42 ReqwestHttpService::new(client.clone()),
43 ReqwestStreamingHttpService::new(client),
44 )
45}
46
47pub trait IntoBoxHttpService: Sized {
49 fn into_box(self) -> BoxHttpService;
51}
52
53impl<S> IntoBoxHttpService for S
54where
55 S: tower::Service<HttpRequest, Response = HttpResponse, Error = Error> + Clone + Send + 'static,
56 S::Future: Send + 'static,
57{
58 fn into_box(self) -> BoxHttpService {
59 BoxHttpService::new(self)
60 }
61}
62
63pub trait IntoBoxStreamingHttpService: Sized {
65 fn into_streaming_box(self) -> BoxStreamingHttpService;
67}
68
69impl<S> IntoBoxStreamingHttpService for S
70where
71 S: tower::Service<HttpRequest, Response = HttpStreamingResponse, Error = Error>
72 + Clone
73 + Send
74 + 'static,
75 S::Future: Send + 'static,
76{
77 fn into_streaming_box(self) -> BoxStreamingHttpService {
78 BoxStreamingHttpService::new(self)
79 }
80}
81
82pub fn with_concurrency_limit(client: reqwest::Client, max_in_flight: usize) -> BoxHttpService {
84 build(client, |inner| {
85 ServiceBuilder::new()
86 .layer(ConcurrencyLimitLayer::new(max_in_flight))
87 .service(inner)
88 .into_box()
89 })
90}
91
92pub fn with_buffer(client: reqwest::Client, capacity: usize) -> BoxHttpService {
99 build(client, |inner| {
100 let buffered = tower::buffer::Buffer::new(inner, capacity);
101 ServiceBuilder::new()
102 .map_err(|e: tower::BoxError| Error::transport_message(e.to_string()))
103 .service(buffered)
104 .into_box()
105 })
106}
107
108pub fn with_request_logging(client: reqwest::Client) -> BoxHttpService {
110 build(client, |inner| {
111 ServiceBuilder::new()
112 .map_request(|req: HttpRequest| {
113 tracing::debug!(method = %req.method, url = %req.url, "better-fetch transport");
114 req
115 })
116 .service(inner)
117 .into_box()
118 })
119}