Skip to content

Commit c65363e

Browse files
authored
[Rust Server] Pass context to client middleware (#6574)
* [Rust Server] Pass context to client middleware When creating a client with middleware, pass the context. This allows users to pass contextual data about the requests through to the client middleware. * Update samples
1 parent aa201b3 commit c65363e

File tree

17 files changed

+448
-270
lines changed

17 files changed

+448
-270
lines changed

modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ use std::io::{ErrorKind, Read};
99
use std::error::Error;
1010
use std::future::Future;
1111
use std::fmt;
12+
use std::marker::PhantomData;
1213
use std::path::Path;
1314
use std::sync::{Arc, Mutex};
1415
use std::str;
1516
use std::str::FromStr;
1617
use std::string::ToString;
1718
use std::task::{Context, Poll};
18-
use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString};
19+
use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString};
1920
use url::form_urlencoded;
2021

2122
{{#apiUsesMultipartFormData}}

modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,49 +27,57 @@ fn into_base_path(input: impl TryInto<Uri, Error=hyper::http::uri::InvalidUri>,
2727
}
2828

2929
/// A client that implements the API by making HTTP calls out to a server.
30-
pub struct Client<S> where
30+
pub struct Client<S, C> where
3131
S: Service<
32-
Request<Body>,
32+
(Request<Body>, C),
3333
Response=Response<Body>> + Clone + Sync + Send + 'static,
3434
S::Future: Send + 'static,
3535
S::Error: Into<crate::ServiceError> + fmt::Display,
36+
C: Clone + Send + Sync + 'static
3637
{
3738
/// Inner service
3839
client_service: S,
3940
4041
/// Base path of the API
4142
base_path: String,
43+
44+
/// Marker
45+
marker: PhantomData<fn(C)>,
4246
}
4347

44-
impl<S> fmt::Debug for Client<S> where
48+
impl<S, C> fmt::Debug for Client<S, C> where
4549
S: Service<
46-
Request<Body>,
50+
(Request<Body>, C),
4751
Response=Response<Body>> + Clone + Sync + Send + 'static,
4852
S::Future: Send + 'static,
4953
S::Error: Into<crate::ServiceError> + fmt::Display,
54+
C: Clone + Send + Sync + 'static
5055
{
5156
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5257
write!(f, "Client {{ base_path: {} }}", self.base_path)
5358
}
5459
}
5560
56-
impl<S> Clone for Client<S> where
61+
impl<S, C> Clone for Client<S, C> where
5762
S: Service<
58-
Request<Body>,
63+
(Request<Body>, C),
5964
Response=Response<Body>> + Clone + Sync + Send + 'static,
6065
S::Future: Send + 'static,
6166
S::Error: Into<crate::ServiceError> + fmt::Display,
67+
C: Clone + Send + Sync + 'static
6268
{
6369
fn clone(&self) -> Self {
6470
Self {
6571
client_service: self.client_service.clone(),
6672
base_path: self.base_path.clone(),
73+
marker: PhantomData,
6774
}
6875
}
6976
}
7077

71-
impl<C> Client<hyper::client::Client<C, Body>> where
72-
C: hyper::client::connect::Connect + Clone + Send + Sync + 'static
78+
impl<Connector, C> Client<DropContextService<hyper::client::Client<Connector, Body>, C>, C> where
79+
Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static,
80+
C: Clone + Send + Sync + 'static,
7381
{
7482
/// Create a client with a custom implementation of hyper::client::Connect.
7583
///
@@ -88,14 +96,16 @@ impl<C> Client<hyper::client::Client<C, Body>> where
8896
pub fn try_new_with_connector(
8997
base_path: &str,
9098
protocol: Option<&'static str>,
91-
connector: C,
99+
connector: Connector,
92100
) -> Result<Self, ClientInitError>
93101
{
94102
let client_service = hyper::client::Client::builder().build(connector);
103+
let client_service = DropContextService::new(client_service);
95104
96105
Ok(Self {
97106
client_service,
98107
base_path: into_base_path(base_path, protocol)?,
108+
marker: PhantomData,
99109
})
100110
}
101111
}
@@ -126,7 +136,9 @@ impl Service<Request<Body>> for HyperClient {
126136
}
127137
}
128138
129-
impl Client<HyperClient> {
139+
impl<C> Client<DropContextService<HyperClient, C>, C> where
140+
C: Clone + Send + Sync + 'static,
141+
{
130142
/// Create an HTTP client.
131143
///
132144
/// # Arguments
@@ -156,14 +168,18 @@ impl Client<HyperClient> {
156168
}
157169
};
158170

171+
let client_service = DropContextService::new(client_service);
172+
159173
Ok(Self {
160174
client_service,
161175
base_path: into_base_path(base_path, None)?,
176+
marker: PhantomData,
162177
})
163178
}
164179
}
165180

166-
impl Client<hyper::client::Client<hyper::client::HttpConnector, Body>>
181+
impl<C> Client<DropContextService<hyper::client::Client<hyper::client::HttpConnector, Body>, C>, C> where
182+
C: Clone + Send + Sync + 'static
167183
{
168184
/// Create an HTTP client.
169185
///
@@ -184,7 +200,8 @@ type HttpsConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;
184200
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
185201
type HttpsConnector = hyper_openssl::HttpsConnector<hyper::client::HttpConnector>;
186202

187-
impl Client<hyper::client::Client<HttpsConnector, Body>>
203+
impl<C> Client<DropContextService<hyper::client::Client<HttpsConnector, Body>, C>, C> where
204+
C: Clone + Send + Sync + 'static
188205
{
189206
/// Create a client with a TLS connection to the server
190207
///
@@ -249,12 +266,13 @@ impl Client<hyper::client::Client<HttpsConnector, Body>>
249266
}
250267
}
251268

252-
impl<S> Client<S> where
269+
impl<S, C> Client<S, C> where
253270
S: Service<
254-
Request<Body>,
271+
(Request<Body>, C),
255272
Response=Response<Body>> + Clone + Sync + Send + 'static,
256273
S::Future: Send + 'static,
257274
S::Error: Into<crate::ServiceError> + fmt::Display,
275+
C: Clone + Send + Sync + 'static
258276
{
259277
/// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` /
260278
/// `tower::Service`
@@ -268,6 +286,7 @@ impl<S> Client<S> where
268286
Ok(Self {
269287
client_service,
270288
base_path: into_base_path(base_path, None)?,
289+
marker: PhantomData,
271290
})
272291
}
273292
}
@@ -313,13 +332,13 @@ impl Error for ClientInitError {
313332
}
314333
315334
#[async_trait]
316-
impl<C, S> Api<C> for Client<S> where
317-
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}} + Clone + Send + Sync + 'static,
335+
impl<S, C> Api<C> for Client<S, C> where
318336
S: Service<
319-
Request<Body>,
337+
(Request<Body>, C),
320338
Response=Response<Body>> + Clone + Sync + Send + 'static,
321339
S::Future: Send + 'static,
322340
S::Error: Into<crate::ServiceError> + fmt::Display,
341+
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}} + Clone + Send + Sync + 'static,
323342
{
324343
fn poll_ready(&self, cx: &mut Context) -> Poll<Result<(), crate::ServiceError>> {
325344
match self.client_service.clone().poll_ready(cx) {

modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
};
135135

136136
*request.body_mut() = Body::from(body_string);
137+
137138
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) {
138139
Ok(h) => h,
139140
Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e)))
@@ -365,7 +366,7 @@
365366
{{/isMapContainer}}
366367

367368
{{/headerParams}}
368-
let mut response = client_service.call(request)
369+
let mut response = client_service.call((request, context.clone()))
369370
.map_err(|e| ApiError(format!("No response received: {}", e))).await?;
370371

371372
match response.status().as_u16() {

modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,53 @@ use crate::{{{operationId}}}Response;
1717
{{/apiInfo}}
1818

1919
/// A client that implements the API by making HTTP calls out to a server.
20-
pub struct Client<S> where
20+
pub struct Client<S, C> where
2121
S: Service<
22-
Request<Body>,
22+
(Request<Body>, C),
2323
Response=Response<Body>,
2424
Error=hyper::Error> + Clone + Send + Sync,
2525
S::Future: Send + 'static,
26+
C: Clone + Send + Sync + 'static
2627
{
2728
/// Inner service
2829
client_service: S,
30+
31+
/// Marker
32+
marker: PhantomData<fn(C)>,
2933
}
3034

31-
impl<S> fmt::Debug for Client<S> where
35+
impl<S, C> fmt::Debug for Client<S, C> where
3236
S: Service<
33-
Request<Body>,
37+
(Request<Body>, C),
3438
Response=Response<Body>,
3539
Error=hyper::Error> + Clone + Send + Sync,
3640
S::Future: Send + 'static,
41+
C: Clone + Send + Sync + 'static
3742
{
3843
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3944
write!(f, "Client")
4045
}
4146
}
4247
43-
impl<S> Clone for Client<S> where
48+
impl<S, C> Clone for Client<S, C> where
4449
S: Service<
45-
Request<Body>,
50+
(Request<Body>, C),
4651
Response=Response<Body>,
4752
Error=hyper::Error> + Clone + Send + Sync,
4853
S::Future: Send + 'static,
54+
C: Clone + Send + Sync + 'static
4955
{
5056
fn clone(&self) -> Self {
5157
Self {
5258
client_service: self.client_service.clone(),
59+
marker: PhantomData,
5360
}
5461
}
5562
}
5663
57-
impl<C> Client<hyper::client::Client<C, Body>> where
58-
C: hyper::client::connect::Connect + Clone + Send + Sync + 'static
64+
impl<Connector, C> Client<DropContextService<hyper::client::Client<Connector, Body>, C>, C> where
65+
Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static,
66+
C: Clone + Send + Sync + 'static
5967
{
6068
/// Create a client with a custom implementation of hyper::client::Connect.
6169
///
@@ -69,17 +77,20 @@ impl<C> Client<hyper::client::Client<C, Body>> where
6977
/// # Arguments
7078
///
7179
/// * `connector` - Implementation of `hyper::client::Connect` to use for the client
72-
pub fn new_with_connector(connector: C) -> Self
80+
pub fn new_with_connector(connector: Connector) -> Self
7381
{
7482
let client_service = hyper::client::Client::builder().build(connector);
83+
let client_service = DropContextService::new(client_service);
7584
7685
Self {
7786
client_service,
87+
marker: PhantomData,
7888
}
7989
}
8090
}
8191
82-
impl Client<hyper::client::Client<hyper::client::HttpConnector, Body>>
92+
impl<C> Client<DropContextService<hyper::client::Client<hyper::client::HttpConnector, Body>, C>, C> where
93+
C: Clone + Send + Sync + 'static
8394
{
8495
/// Create an HTTP client.
8596
pub fn new_http() -> Self {
@@ -94,7 +105,8 @@ type HttpConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;
94105
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
95106
type HttpsConnector = hyper_openssl::HttpsConnector<hyper::client::HttpConnector>;
96107

97-
impl Client<hyper::client::Client<HttpsConnector, Body>>
108+
impl<C> Client<DropContextService<hyper::client::Client<HttpsConnector, Body>, C>, C> where
109+
C: Clone + Send + Sync + 'static
98110
{
99111
/// Create a client with a TLS connection to the server.
100112
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
@@ -155,12 +167,13 @@ impl Client<hyper::client::Client<HttpsConnector, Body>>
155167
}
156168
}
157169

158-
impl<S> Client<S> where
170+
impl<S, C> Client<S, C> where
159171
S: Service<
160-
Request<Body>,
172+
(Request<Body>, C),
161173
Response=Response<Body>,
162174
Error=hyper::Error> + Clone + Send + Sync,
163175
S::Future: Send + 'static,
176+
C: Clone + Send + Sync + 'static
164177
{
165178
/// Constructor for creating a `Client` by passing in a pre-made `swagger::Service`
166179
///
@@ -170,19 +183,20 @@ impl<S> Client<S> where
170183
) -> Self {
171184
Client {
172185
client_service,
186+
marker: PhantomData,
173187
}
174188
}
175189
}
176190

177191
#[async_trait]
178-
impl<C, S> CallbackApi<C> for Client<S> where
179-
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}} + Send + Sync,
192+
impl<S, C> CallbackApi<C> for Client<S, C> where
180193
S: Service<
181-
Request<Body>,
194+
(Request<Body>, C),
182195
Response=Response<Body>,
183196
Error=hyper::Error> + Clone + Send + Sync,
184197
S::Future: Send + 'static,
185198
S::Error: Into<crate::ServiceError> + fmt::Display,
199+
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}} + Clone + Send + Sync,
186200
{
187201
fn poll_ready(&self, cx: &mut Context) -> Poll<Result<(), crate::ServiceError>> {
188202
match self.client_service.clone().poll_ready(cx) {

samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator/FILES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.cargo/config
22
.gitignore
3+
.openapi-generator-ignore
34
Cargo.toml
45
README.md
56
api/openapi.yaml

0 commit comments

Comments
 (0)