Skip to content

Commit bb831da

Browse files
wing328blazzy
andauthored
Make the rust hyper client Send so it can be used in rust threads more easily (#19375)
* Add externCrateName property to rust hyper client This is follows the lead of the rust hyper server generator and provides an externCrateName. This is because the crate name used for importing can be different from the package name, because dashes `-` get converted to underscores `_`. This allows us to write example code in rustdoc that compiles successfully. * Get the rustdoc examples to actually compile * Make rust hyper client thread safe * Fix compile time issue with reqwest client test * Add a test for thread safety * Generate rust hyper samples * Use https for petstore api to fix client tests http://petstore.swagger.io/v2 is 301 redirecting to https://petstore.swagger.io/v2 and this is breaking posts to the API. When the client recieves a redirect it does not resend the POST data, instead it switches to GET. This is in line with how browsers behave when encountering a 301 redirect on a POST request. * Make rust hyper client structs `Sync` too This trait is also helpful in making the api work well with threads. * Use a getCrateName function instead of adding more state * update samples --------- Co-authored-by: Krishna Rajendran <krishna@emptybox.org>
1 parent 172fafe commit bb831da

39 files changed

Lines changed: 248 additions & 176 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
5555
@Setter private boolean avoidBoxedModels = false;
5656

5757
public static final String PACKAGE_NAME = "packageName";
58+
public static final String EXTERN_CRATE_NAME = "externCrateName";
5859
public static final String PACKAGE_VERSION = "packageVersion";
5960
public static final String HYPER_LIBRARY = "hyper";
6061
public static final String HYPER0X_LIBRARY = "hyper0x";
@@ -367,6 +368,7 @@ public void processOpts() {
367368

368369
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
369370
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
371+
additionalProperties.put(EXTERN_CRATE_NAME, getExternCrateName());
370372

371373
additionalProperties.put("apiDocPath", apiDocPath);
372374
additionalProperties.put("modelDocPath", modelDocPath);
@@ -423,6 +425,11 @@ public void execute(Template.Fragment fragment, Writer writer) throws IOExceptio
423425

424426
}
425427

428+
private String getExternCrateName() {
429+
// The external name used when importing a crate has all '-' replaced with '_'.
430+
return packageName.replace('-', '_');
431+
}
432+
426433
private boolean getSupportAsync() {
427434
return supportAsync;
428435
}

modules/openapi-generator/src/main/resources/rust/hyper/api.mustache

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{>partial_header}}
2-
use std::rc::Rc;
2+
use std::sync::Arc;
33
use std::borrow::Borrow;
44
use std::pin::Pin;
55
#[allow(unused_imports)]
@@ -15,22 +15,22 @@ use super::request as __internal_request;
1515

1616
pub struct {{{classname}}}Client<C: Connect>
1717
where C: Clone + std::marker::Send + Sync + 'static {
18-
configuration: Rc<configuration::Configuration<C>>,
18+
configuration: Arc<configuration::Configuration<C>>,
1919
}
2020

2121
impl<C: Connect> {{{classname}}}Client<C>
2222
where C: Clone + std::marker::Send + Sync {
23-
pub fn new(configuration: Rc<configuration::Configuration<C>>) -> {{{classname}}}Client<C> {
23+
pub fn new(configuration: Arc<configuration::Configuration<C>>) -> {{{classname}}}Client<C> {
2424
{{{classname}}}Client {
2525
configuration,
2626
}
2727
}
2828
}
2929

30-
pub trait {{{classname}}} {
30+
pub trait {{{classname}}}: Send + Sync {
3131
{{#operations}}
3232
{{#operation}}
33-
fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{^isUuid}}&str{{/isUuid}}{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin<Box<dyn Future<Output = Result<{{^returnType}}(){{/returnType}}{{#returnType}}{{{returnType}}}{{/returnType}}, Error>>>>;
33+
fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{^isUuid}}&str{{/isUuid}}{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin<Box<dyn Future<Output = Result<{{^returnType}}(){{/returnType}}{{#returnType}}{{{returnType}}}{{/returnType}}, Error>> + Send>>;
3434
{{/operation}}
3535
{{/operations}}
3636
}
@@ -40,7 +40,7 @@ impl<C: Connect>{{{classname}}} for {{{classname}}}Client<C>
4040
{{#operations}}
4141
{{#operation}}
4242
#[allow(unused_mut)]
43-
fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{^isUuid}}&str{{/isUuid}}{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin<Box<dyn Future<Output = Result<{{^returnType}}(){{/returnType}}{{#returnType}}{{{.}}}{{/returnType}}, Error>>>> {
43+
fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{^isUuid}}&str{{/isUuid}}{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin<Box<dyn Future<Output = Result<{{^returnType}}(){{/returnType}}{{#returnType}}{{{.}}}{{/returnType}}, Error>> + Send>> {
4444
let mut req = __internal_request::Request::new(hyper::Method::{{{httpMethod.toUpperCase}}}, "{{{path}}}".to_string())
4545
{{#hasAuthMethods}}
4646
{{#authMethods}}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::rc::Rc;
1+
use std::sync::Arc;
22

33
use hyper;
44
use hyper_util::client::legacy::connect::Connect;
@@ -21,7 +21,7 @@ pub struct APIClient {
2121
impl APIClient {
2222
pub fn new<C: Connect>(configuration: Configuration<C>) -> APIClient
2323
where C: Clone + std::marker::Send + Sync + 'static {
24-
let rc = Rc::new(configuration);
24+
let rc = Arc::new(configuration);
2525
2626
APIClient {
2727
{{#apiInfo}}

modules/openapi-generator/src/main/resources/rust/hyper/configuration.mustache

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ impl Configuration<HttpConnector> {
3333
/// # Example
3434
///
3535
/// ```
36-
/// let api_config = {
37-
/// api_key: "my-api-key",
38-
/// ...Configuration::new()
39-
/// }
36+
/// # use {{externCrateName}}::apis::configuration::Configuration;
37+
/// let api_config = Configuration {
38+
/// basic_auth: Some(("user".into(), None)),
39+
/// ..Configuration::new()
40+
/// };
4041
/// ```
4142
pub fn new() -> Configuration<HttpConnector> {
4243
Configuration::default()
@@ -51,6 +52,11 @@ impl<C: Connect> Configuration<C>
5152
/// # Example
5253
///
5354
/// ```
55+
/// # use core::time::Duration;
56+
/// # use {{externCrateName}}::apis::configuration::Configuration;
57+
/// use hyper_util::client::legacy::Client;
58+
/// use hyper_util::rt::TokioExecutor;
59+
///
5460
/// let client = Client::builder(TokioExecutor::new())
5561
/// .pool_idle_timeout(Duration::from_secs(30))
5662
/// .build_http();

modules/openapi-generator/src/main/resources/rust/request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl Request {
109109
pub fn execute<'a, C, U>(
110110
self,
111111
conf: &configuration::Configuration<C>,
112-
) -> Pin<Box<dyn Future<Output=Result<U, Error>> + 'a>>
112+
) -> Pin<Box<dyn Future<Output=Result<U, Error>> + 'a + Send>>
113113
where
114114
C: Connect + Clone + std::marker::Send + Sync,
115115
U: Sized + std::marker::Send + 'a,

samples/client/others/rust/hyper/api-with-ref-param/src/apis/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::rc::Rc;
1+
use std::sync::Arc;
22

33
use hyper;
44
use hyper_util::client::legacy::connect::Connect;
@@ -11,7 +11,7 @@ pub struct APIClient {
1111
impl APIClient {
1212
pub fn new<C: Connect>(configuration: Configuration<C>) -> APIClient
1313
where C: Clone + std::marker::Send + Sync + 'static {
14-
let rc = Rc::new(configuration);
14+
let rc = Arc::new(configuration);
1515

1616
APIClient {
1717
default_api: Box::new(crate::apis::DefaultApiClient::new(rc.clone())),

samples/client/others/rust/hyper/api-with-ref-param/src/apis/configuration.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ impl Configuration<HttpConnector> {
4242
/// # Example
4343
///
4444
/// ```
45-
/// let api_config = {
46-
/// api_key: "my-api-key",
47-
/// ...Configuration::new()
48-
/// }
45+
/// # use api_ref_param_hyper::apis::configuration::Configuration;
46+
/// let api_config = Configuration {
47+
/// basic_auth: Some(("user".into(), None)),
48+
/// ..Configuration::new()
49+
/// };
4950
/// ```
5051
pub fn new() -> Configuration<HttpConnector> {
5152
Configuration::default()
@@ -60,6 +61,11 @@ impl<C: Connect> Configuration<C>
6061
/// # Example
6162
///
6263
/// ```
64+
/// # use core::time::Duration;
65+
/// # use api_ref_param_hyper::apis::configuration::Configuration;
66+
/// use hyper_util::client::legacy::Client;
67+
/// use hyper_util::rt::TokioExecutor;
68+
///
6369
/// let client = Client::builder(TokioExecutor::new())
6470
/// .pool_idle_timeout(Duration::from_secs(30))
6571
/// .build_http();

samples/client/others/rust/hyper/api-with-ref-param/src/apis/default_api.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Generated by: https://openapi-generator.tech
99
*/
1010

11-
use std::rc::Rc;
11+
use std::sync::Arc;
1212
use std::borrow::Borrow;
1313
use std::pin::Pin;
1414
#[allow(unused_imports)]
@@ -24,26 +24,26 @@ use super::request as __internal_request;
2424

2525
pub struct DefaultApiClient<C: Connect>
2626
where C: Clone + std::marker::Send + Sync + 'static {
27-
configuration: Rc<configuration::Configuration<C>>,
27+
configuration: Arc<configuration::Configuration<C>>,
2828
}
2929

3030
impl<C: Connect> DefaultApiClient<C>
3131
where C: Clone + std::marker::Send + Sync {
32-
pub fn new(configuration: Rc<configuration::Configuration<C>>) -> DefaultApiClient<C> {
32+
pub fn new(configuration: Arc<configuration::Configuration<C>>) -> DefaultApiClient<C> {
3333
DefaultApiClient {
3434
configuration,
3535
}
3636
}
3737
}
3838

39-
pub trait DefaultApi {
40-
fn demo_color_get(&self, color: models::Color) -> Pin<Box<dyn Future<Output = Result<(), Error>>>>;
39+
pub trait DefaultApi: Send + Sync {
40+
fn demo_color_get(&self, color: models::Color) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>>;
4141
}
4242

4343
impl<C: Connect>DefaultApi for DefaultApiClient<C>
4444
where C: Clone + std::marker::Send + Sync {
4545
#[allow(unused_mut)]
46-
fn demo_color_get(&self, color: models::Color) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
46+
fn demo_color_get(&self, color: models::Color) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send>> {
4747
let mut req = __internal_request::Request::new(hyper::Method::GET, "/demo/{color}".to_string())
4848
;
4949
req = req.with_path_param("color".to_string(), color.to_string());

samples/client/others/rust/hyper/api-with-ref-param/src/apis/request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl Request {
109109
pub fn execute<'a, C, U>(
110110
self,
111111
conf: &configuration::Configuration<C>,
112-
) -> Pin<Box<dyn Future<Output=Result<U, Error>> + 'a>>
112+
) -> Pin<Box<dyn Future<Output=Result<U, Error>> + 'a + Send>>
113113
where
114114
C: Connect + Clone + std::marker::Send + Sync,
115115
U: Sized + std::marker::Send + 'a,

samples/client/others/rust/hyper/composed-oneof/src/apis/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::rc::Rc;
1+
use std::sync::Arc;
22

33
use hyper;
44
use hyper_util::client::legacy::connect::Connect;
@@ -11,7 +11,7 @@ pub struct APIClient {
1111
impl APIClient {
1212
pub fn new<C: Connect>(configuration: Configuration<C>) -> APIClient
1313
where C: Clone + std::marker::Send + Sync + 'static {
14-
let rc = Rc::new(configuration);
14+
let rc = Arc::new(configuration);
1515

1616
APIClient {
1717
default_api: Box::new(crate::apis::DefaultApiClient::new(rc.clone())),

0 commit comments

Comments
 (0)