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 {
88 build(client, |inner| {
89 ServiceBuilder::new()
90 .layer(ConcurrencyLimitLayer::new(max_in_flight))
91 .service(inner)
92 .into_box()
93 })
94}
95
96pub fn with_buffer(client: reqwest::Client, capacity: usize) -> BoxHttpService {
103 build(client, |inner| {
104 let buffered = tower::buffer::Buffer::new(inner, capacity);
105 ServiceBuilder::new()
106 .map_err(|e: tower::BoxError| Error::transport_message(e.to_string()))
107 .service(buffered)
108 .into_box()
109 })
110}
111
112pub fn with_request_logging(client: reqwest::Client) -> BoxHttpService {
114 build(client, |inner| {
115 ServiceBuilder::new()
116 .map_request(|req: HttpRequest| {
117 tracing::debug!(method = %req.method, url = %req.url, "better-fetch transport");
118 req
119 })
120 .service(inner)
121 .into_box()
122 })
123}