From 7ab93640942ea494dc18a28a437a13de26d08e8a Mon Sep 17 00:00:00 2001 From: Jean-Marc Le Roux Date: Wed, 1 Oct 2025 19:47:08 +0200 Subject: [PATCH] [Rust] Configurable default features from reqwest dependency (#22041) * fix(rust): Remove default features from reqwest dependency This change removes the default features (specifically native-tls) from the reqwest dependency in the Rust client generator. This allows users to explicitly choose their TLS backend without automatically including openssl-sys as a transitive dependency. Users can now explicitly enable TLS backends using feature flags: - native-tls - rustls-tls - default-tls Fixes #21933 * feat(rust): Add reqwestDefaultFeatures option with backward-compatible default This change adds a new generator option `reqwestDefaultFeatures` that allows users to configure the default Cargo features for the reqwest dependency. The option accepts: - An array of strings in YAML config: reqwestDefaultFeatures: ["native-tls"] - A comma-separated string via CLI: --additional-properties=reqwestDefaultFeatures=native-tls - An empty value for no defaults: reqwestDefaultFeatures: [] Default value: ["native-tls"] (maintains backward compatibility) This addresses the feedback in #21933 to make the change opt-in rather than breaking existing users. Users can now: - Keep the current behavior (default) - Opt-out: reqwestDefaultFeatures: [] - Use alternative TLS: reqwestDefaultFeatures: ["rustls-tls"] - Combine features: reqwestDefaultFeatures: ["native-tls", "cookies"] Fixes #21933 --- docs/generators/rust.md | 1 + .../codegen/languages/RustClientCodegen.java | 19 +++++++++++++++++++ .../src/main/resources/rust/Cargo.mustache | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/generators/rust.md b/docs/generators/rust.md index d3bf7882933..67f868e67af 100644 --- a/docs/generators/rust.md +++ b/docs/generators/rust.md @@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |packageName|Rust package name (convention: lowercase).| |openapi| |packageVersion|Rust package version.| |1.0.0| |preferUnsignedInt|Prefer unsigned integers where minimum value is >= 0| |false| +|reqwestDefaultFeatures|Default features for the reqwest dependency (comma-separated). Use empty for no defaults. This option is for 'reqwest' and 'reqwest-trait' library only.| |native-tls| |supportAsync|If set, generate async function call instead. This option is for 'reqwest' library only| |true| |supportMiddleware|If set, add support for reqwest-middleware. This option is for 'reqwest' and 'reqwest-trait' library only| |false| |supportMultipleResponses|If set, return type wraps an enum of all possible 2xx schemas. This option is for 'reqwest' and 'reqwest-trait' library only| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java index b1727a6f3d6..a062968285b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java @@ -58,6 +58,7 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon @Setter private boolean preferUnsignedInt = false; @Setter private boolean bestFitInt = false; @Setter private boolean avoidBoxedModels = false; + private List reqwestDefaultFeatures = Arrays.asList("native-tls"); public static final String PACKAGE_NAME = "packageName"; public static final String EXTERN_CRATE_NAME = "externCrateName"; @@ -77,6 +78,7 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon public static final String TOP_LEVEL_API_CLIENT = "topLevelApiClient"; public static final String MOCKALL = "mockall"; public static final String BON_BUILDER = "useBonBuilder"; + public static final String REQWEST_DEFAULT_FEATURES = "reqwestDefaultFeatures"; @Setter protected String packageName = "openapi"; @Setter protected String packageVersion = "1.0.0"; @@ -227,6 +229,8 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon .defaultValue(Boolean.FALSE.toString())); cliOptions.add(new CliOption(BON_BUILDER, "Use the bon crate for building parameter types. This option is for the 'reqwest-trait' library only", SchemaTypeUtil.BOOLEAN_TYPE) .defaultValue(Boolean.FALSE.toString())); + cliOptions.add(new CliOption(REQWEST_DEFAULT_FEATURES, "Default features for the reqwest dependency (comma-separated). Use empty for no defaults. This option is for 'reqwest' and 'reqwest-trait' library only.") + .defaultValue("native-tls")); supportedLibraries.put(HYPER_LIBRARY, "HTTP client: Hyper (v1.x)."); supportedLibraries.put(HYPER0X_LIBRARY, "HTTP client: Hyper (v0.x)."); @@ -431,6 +435,21 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon } writePropertyBack(AVOID_BOXED_MODELS, getAvoidBoxedModels()); + if (additionalProperties.containsKey(REQWEST_DEFAULT_FEATURES)) { + Object value = additionalProperties.get(REQWEST_DEFAULT_FEATURES); + if (value instanceof List) { + reqwestDefaultFeatures = (List) value; + } else if (value instanceof String) { + String str = (String) value; + if (str.isEmpty()) { + reqwestDefaultFeatures = new ArrayList<>(); + } else { + reqwestDefaultFeatures = Arrays.asList(str.split(",\\s*")); + } + } + } + additionalProperties.put(REQWEST_DEFAULT_FEATURES, reqwestDefaultFeatures); + additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion); additionalProperties.put(EXTERN_CRATE_NAME, getExternCrateName()); diff --git a/modules/openapi-generator/src/main/resources/rust/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust/Cargo.mustache index 459cf3d6cb7..6073f156810 100644 --- a/modules/openapi-generator/src/main/resources/rust/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust/Cargo.mustache @@ -88,7 +88,7 @@ google-cloud-token = "^0.1" {{/supportAsync}} [features] -default = ["native-tls"] +default = [{{#reqwestDefaultFeatures}}"{{.}}"{{^-last}}, {{/-last}}{{/reqwestDefaultFeatures}}] native-tls = ["reqwest/native-tls"] rustls-tls = ["reqwest/rustls-tls"] {{/reqwest}} @@ -109,7 +109,7 @@ mockall = { version = "^0.13", optional = true} bon = { version = "2.3", optional = true } {{/useBonBuilder}} [features] -default = ["native-tls"] +default = [{{#reqwestDefaultFeatures}}"{{.}}"{{^-last}}, {{/-last}}{{/reqwestDefaultFeatures}}] native-tls = ["reqwest/native-tls"] rustls-tls = ["reqwest/rustls-tls"] {{#mockall}}