Skip to content

Commit 62fc5fd

Browse files
committed
An interface is still nice here
1 parent fe8bb61 commit 62fc5fd

File tree

4 files changed

+44
-20
lines changed

4 files changed

+44
-20
lines changed

crates/twirp-build/src/lib.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ where
6969
//
7070
writeln!(buf).unwrap();
7171
writeln!(buf, "#[async_trait::async_trait]").unwrap();
72-
writeln!(buf, "pub trait {}Client {{", service_name).unwrap();
72+
writeln!(
73+
buf,
74+
"pub trait {}Client: Send + Sync + std::fmt::Debug {{",
75+
service_name
76+
)
77+
.unwrap();
7378
for m in &service.methods {
7479
// Define: <METHOD>
7580
writeln!(
@@ -81,11 +86,11 @@ where
8186
}
8287
writeln!(buf, "}}").unwrap();
8388

84-
// Implement the `twirp::client::TwirpClient` trait
89+
// Implement the `twirp::client::HttpTwirpClient` trait
8590
writeln!(buf, "#[async_trait::async_trait]").unwrap();
8691
writeln!(
8792
buf,
88-
"impl {}Client for twirp::client::TwirpClient {{",
93+
"impl {}Client for twirp::client::HttpTwirpClient {{",
8994
service_name
9095
)
9196
.unwrap();
@@ -103,7 +108,11 @@ where
103108
service_fqn, m.proto_name,
104109
)
105110
.unwrap();
106-
writeln!(buf, " self.request(url, req).await",).unwrap();
111+
writeln!(
112+
buf,
113+
" twirp::client::TwirpClient::request(self, url, req).await",
114+
)
115+
.unwrap();
107116
writeln!(buf, " }}").unwrap();
108117
}
109118
writeln!(buf, "}}").unwrap();

crates/twirp/src/client.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,21 @@ impl TwirpClientBuilder {
7878
}
7979
}
8080

81-
pub fn build(self) -> Result<TwirpClient> {
82-
TwirpClient::new(self.base_url, self.builder, self.middleware)
81+
pub fn build(self) -> Result<HttpTwirpClient> {
82+
HttpTwirpClient::new(self.base_url, self.builder, self.middleware)
8383
}
8484
}
8585

8686
/// `HttpTwirpClient` is a TwirpClient that uses `reqwest::Client` to make http
8787
/// requests.
8888
#[derive(Clone)]
89-
pub struct TwirpClient {
89+
pub struct HttpTwirpClient {
9090
pub base_url: Arc<Url>,
9191
client: Arc<reqwest::Client>,
9292
middlewares: Vec<Arc<dyn Middleware>>,
9393
}
9494

95-
impl std::fmt::Debug for TwirpClient {
95+
impl std::fmt::Debug for HttpTwirpClient {
9696
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9797
f.debug_struct("TwirpClient")
9898
.field("base_url", &self.base_url)
@@ -102,7 +102,19 @@ impl std::fmt::Debug for TwirpClient {
102102
}
103103
}
104104

105-
impl TwirpClient {
105+
#[async_trait]
106+
pub trait TwirpClient {
107+
fn with<M>(&self, middleware: M) -> Self
108+
where
109+
M: Middleware;
110+
111+
async fn request<I, O>(&self, url: Url, body: I) -> Result<O>
112+
where
113+
I: prost::Message,
114+
O: prost::Message + Default;
115+
}
116+
117+
impl HttpTwirpClient {
106118
/// Creates a TwirpClient with the default `reqwest::ClientBuilder`.
107119
///
108120
/// The underlying `reqwest::Client` holds a connection pool internally, so it is advised that
@@ -127,14 +139,17 @@ impl TwirpClient {
127139
let mut headers: HeaderMap<HeaderValue> = HeaderMap::default();
128140
headers.insert(CONTENT_TYPE, CONTENT_TYPE_PROTOBUF.try_into()?);
129141
let client = b.default_headers(headers).build()?;
130-
Ok(TwirpClient {
142+
Ok(HttpTwirpClient {
131143
base_url: Arc::new(base_url),
132144
client: Arc::new(client),
133145
middlewares,
134146
})
135147
}
148+
}
136149

137-
pub fn with<M>(&self, middleware: M) -> Self
150+
#[async_trait]
151+
impl TwirpClient for HttpTwirpClient {
152+
fn with<M>(&self, middleware: M) -> Self
138153
where
139154
M: Middleware,
140155
{
@@ -147,7 +162,7 @@ impl TwirpClient {
147162
}
148163
}
149164

150-
pub async fn request<I, O>(&self, url: Url, body: I) -> Result<O>
165+
async fn request<I, O>(&self, url: Url, body: I) -> Result<O>
151166
where
152167
I: prost::Message,
153168
O: prost::Message + Default,
@@ -263,10 +278,10 @@ mod tests {
263278
#[tokio::test]
264279
async fn test_base_url() {
265280
let url = Url::parse("http://localhost:3001/twirp/").unwrap();
266-
assert!(TwirpClient::default(url).is_ok());
281+
assert!(HttpTwirpClient::default(url).is_ok());
267282
let url = Url::parse("http://localhost:3001/twirp").unwrap();
268283
assert_eq!(
269-
TwirpClient::default(url).unwrap_err().to_string(),
284+
HttpTwirpClient::default(url).unwrap_err().to_string(),
270285
"base_url must end in /, but got: http://localhost:3001/twirp",
271286
);
272287
}
@@ -293,7 +308,7 @@ mod tests {
293308
async fn test_standard_client() {
294309
let h = run_test_server(3001).await;
295310
let base_url = Url::parse("http://localhost:3001/twirp/").unwrap();
296-
let client = TwirpClient::default(base_url).unwrap();
311+
let client = HttpTwirpClient::default(base_url).unwrap();
297312
let resp = client
298313
.ping(PingRequest {
299314
name: "hi".to_string(),

crates/twirp/src/test.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hyper::{Body, Request, Server};
88
use serde::de::DeserializeOwned;
99
use tokio::task::JoinHandle;
1010

11-
use crate::client::{TwirpClient, TwirpClientError};
11+
use crate::client::{HttpTwirpClient, TwirpClientError};
1212
use crate::*;
1313

1414
pub async fn run_test_server(port: u16) -> JoinHandle<Result<(), hyper::Error>> {
@@ -102,10 +102,10 @@ pub trait TestAPIClient {
102102
}
103103

104104
#[async_trait]
105-
impl TestAPIClient for TwirpClient {
105+
impl TestAPIClient for HttpTwirpClient {
106106
async fn ping(&self, req: PingRequest) -> Result<PingResponse, TwirpClientError> {
107107
let url = self.base_url.join("test.TestAPI/Ping")?;
108-
self.request(url, req).await
108+
client::TwirpClient::request(self, url, req).await
109109
}
110110

111111
async fn boom(&self, _req: PingRequest) -> Result<PingResponse, TwirpClientError> {

example/src/bin/example-client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use async_trait::async_trait;
2-
use twirp::client::{Middleware, Next, TwirpClient, TwirpClientBuilder};
2+
use twirp::client::{HttpTwirpClient, Middleware, Next, TwirpClient, TwirpClientBuilder};
33
use twirp::reqwest::{Request, Response};
44
use twirp::url::Url;
55
use twirp::GenericError;
@@ -18,7 +18,7 @@ use service::haberdash::v1::MakeHatRequest;
1818
pub async fn main() -> Result<(), GenericError> {
1919
// basic client
2020
use service::haberdash::v1::HaberdasherAPIClient;
21-
let client = TwirpClient::default(Url::parse("http://localhost:3000/twirp/")?)?;
21+
let client = HttpTwirpClient::default(Url::parse("http://localhost:3000/twirp/")?)?;
2222
let resp = client.make_hat(MakeHatRequest { inches: 1 }).await;
2323
eprintln!("{:?}", resp);
2424

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy