diff --git a/modules/openapi-generator/src/main/resources-override/rust-wasm/Cargo.mustache b/modules/openapi-generator/src/main/resources-override/rust-wasm/Cargo.mustache new file mode 100644 index 00000000000..7f0db0f8444 --- /dev/null +++ b/modules/openapi-generator/src/main/resources-override/rust-wasm/Cargo.mustache @@ -0,0 +1,137 @@ +[package] +name = "{{{packageName}}}" +version = "{{#lambdaVersion}}{{{packageVersion}}}{{/lambdaVersion}}" +{{#infoEmail}} +authors = ["{{{.}}}"] +{{/infoEmail}} +{{^infoEmail}} +authors = ["OpenAPI Generator team and contributors"] +{{/infoEmail}} +{{#appDescription}} +description = "{{{.}}}" +{{/appDescription}} +{{#licenseInfo}} +license = "{{.}}" +{{/licenseInfo}} +{{^licenseInfo}} +# Override this license by providing a License Object in the OpenAPI. +license = "Unlicense" +{{/licenseInfo}} +edition = "2021" +{{#publishRustRegistry}} +publish = ["{{.}}"] +{{/publishRustRegistry}} +{{#repositoryUrl}} +repository = "{{.}}" +{{/repositoryUrl}} +{{#documentationUrl}} +documentation = "{{.}}" +{{/documentationUrl}} +{{#homePageUrl}} +homepage = "{{.}}" +{{/homePageUrl}} + +{{#supportWasm}} +[lib] +crate-type = ["cdylib", "rlib"] +{{/supportWasm}} + +[dependencies] +serde = { version = "^1.0", features = ["derive"] } +{{#serdeWith}} +serde_with = { version = "^3.8", default-features = false, features = ["base64", "std", "macros"] } +{{/serdeWith}} +serde_json = "^1.0" +serde_repr = "^0.1" +url = "^2.5" +{{#hasUUIDs}} +uuid = { version = "^1.8", features = ["serde", "v4"] } +{{/hasUUIDs}} +{{#hyper}} +{{#hyper0x}} +hyper = { version = "~0.14", features = ["full"] } +hyper-tls = "~0.5" +{{/hyper0x}} +{{^hyper0x}} +hyper = { version = "^1.3.1", features = ["full"] } +hyper-util = { version = "0.1.5", features = ["client", "client-legacy", "http1", "http2"] } +http-body-util = { version = "0.1.2" } +{{/hyper0x}} +http = "~0.2" +base64 = "~0.7.0" +futures = "^0.3" +{{/hyper}} +{{#withAWSV4Signature}} +aws-sigv4 = "0.3.0" +http = "0.2.5" +secrecy = "0.8.0" +{{/withAWSV4Signature}} +{{#reqwest}} +{{^supportAsync}} +reqwest = { version = "^0.12", default-features = false, features = ["json", "blocking", "multipart"] } +{{#supportMiddleware}} +reqwest-middleware = { version = "^0.4", features = ["json", "blocking", "multipart"] } +{{/supportMiddleware}} +{{/supportAsync}} +{{#supportAsync}} +reqwest = { version = "^0.12", default-features = false, features = ["json", "multipart"] } +{{#supportMiddleware}} +reqwest-middleware = { version = "^0.4", features = ["json", "multipart"] } +{{/supportMiddleware}} +{{#supportTokenSource}} +async-trait = "^0.1" +# TODO: propose to Yoshidan to externalize this as non google related crate, so that it can easily be extended for other cloud providers. +google-cloud-token = "^0.1" +{{/supportTokenSource}} +{{/supportAsync}} +{{/reqwest}} +{{#reqwestTrait}} +async-trait = "^0.1" +reqwest = { version = "^0.12", default-features = false, features = ["json", "multipart"] } +{{#supportMiddleware}} +reqwest-middleware = { version = "^0.4", features = ["json", "multipart"] } +{{/supportMiddleware}} +{{#supportTokenSource}} +# TODO: propose to Yoshidan to externalize this as non google related crate, so that it can easily be extended for other cloud providers. +google-cloud-token = "^0.1" +{{/supportTokenSource}} +{{#mockall}} +mockall = { version = "^0.13", optional = true} +{{/mockall}} +{{#useBonBuilder}} +bon = { version = "2.3", optional = true } +{{/useBonBuilder}} +[features] +default = [{{#supportWasm}}"console_error_panic_hook"{{/supportWasm}}{{^supportWasm}}"native-tls"{{/supportWasm}}] +{{^supportWasm}} +native-tls = ["reqwest/native-tls"] +rustls = ["reqwest/rustls-tls"] +{{/supportWasm}} +{{#supportWasm}} +console_error_panic_hook = ["dep:console_error_panic_hook"] +{{/supportWasm}} +{{#mockall}} +mockall = ["dep:mockall"] +{{/mockall}} +{{#useBonBuilder}} +bon = ["dep:bon"] +{{/useBonBuilder}} +{{/reqwestTrait}} + +{{#supportWasm}} +console_error_panic_hook = { version = "0.1", optional = true } +js-sys = "0.3" +serde-wasm-bindgen = "^0.6" +wasm-std = { version = "0.0.1", registry = "unbox-x-group" } +wasm-bindgen = { version = "^0.2", features = ["serde-serialize"] } +wasm-bindgen-futures = "^0.4" +{{/supportWasm}} + + +[dev-dependencies] +{{#supportWasm}} +wasm-bindgen-test = "0.3" +{{/supportWasm}} + +[profile.release] +opt-level = "s" \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources-override/rust-wasm/lib.mustache b/modules/openapi-generator/src/main/resources-override/rust-wasm/lib.mustache new file mode 100644 index 00000000000..b2a933fb37e --- /dev/null +++ b/modules/openapi-generator/src/main/resources-override/rust-wasm/lib.mustache @@ -0,0 +1,24 @@ +{{#supportWasm}} +#![no_std] +{{/supportWasm}} +#![allow(unused_imports)] +#![allow(clippy::too_many_arguments)] + +{{#supportWasm}} +extern crate alloc; +{{/supportWasm}} + +extern crate serde_repr; +extern crate serde; +extern crate serde_json; +extern crate url; +{{#hyper}} +extern crate hyper; +extern crate futures; +{{/hyper}} +{{#reqwest}} +extern crate reqwest; +{{/reqwest}} + +pub mod apis; +pub mod models; diff --git a/modules/openapi-generator/src/main/resources-override/rust-wasm/model.mustache b/modules/openapi-generator/src/main/resources-override/rust-wasm/model.mustache new file mode 100644 index 00000000000..c1006665077 --- /dev/null +++ b/modules/openapi-generator/src/main/resources-override/rust-wasm/model.mustache @@ -0,0 +1,241 @@ +{{>partial_header}} +use crate::models; +use serde::{Deserialize, Serialize}; +{{#supportWasm}} +use alloc::borrow::{Cow, ToOwned}; +use alloc::boxed::Box; +use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList}; +use alloc::rc::Rc; +use alloc::string::{String, ToString}; +use alloc::sync::Arc; +use alloc::vec::Vec; +use alloc::{fmt, format, vec}; +use wasm_std::{error, io}; +{{/supportWasm}} + +{{#models}} +{{#model}} +{{^isEnum}}{{#vendorExtensions.x-rust-has-byte-array}} +use serde_with::serde_as; +{{/vendorExtensions.x-rust-has-byte-array}}{{/isEnum}} +{{#isEnum}} +{{#isInteger}} +use serde_repr::{Serialize_repr,Deserialize_repr}; +{{/isInteger}} +{{/isEnum}} +{{#description}} +/// {{{classname}}} : {{{description}}} +{{/description}} +{{!-- for repr(int) enum schemas --}} +{{#isEnum}} +{{#isInteger}} +/// {{{description}}} +#[repr(i64)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr)] +pub enum {{{classname}}} { +{{#allowableValues}} +{{#enumVars}} + {{{name}}} = {{{value}}}, +{{/enumVars}}{{/allowableValues}} +} + +impl std::fmt::Display for {{{classname}}} { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + {{#allowableValues}} + {{#enumVars}} + Self::{{{name}}} => "{{{value}}}", + {{/enumVars}} + {{/allowableValues}} + }) + } +} +{{/isInteger}} +{{/isEnum}} +{{!-- for enum schemas --}} +{{#isEnum}} +{{^isInteger}} +{{#description}} +/// {{{description}}} +{{/description}} +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum {{{classname}}} { +{{#allowableValues}} +{{#enumVars}} + #[serde(rename = "{{{value}}}")] + {{{name}}}, +{{/enumVars}}{{/allowableValues}} +} + +impl std::fmt::Display for {{{classname}}} { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + {{#allowableValues}} + {{#enumVars}} + Self::{{{name}}} => write!(f, "{{{value}}}"), + {{/enumVars}} + {{/allowableValues}} + } + } +} + +{{/isInteger}} +impl Default for {{{classname}}} { + fn default() -> {{{classname}}} { + {{#allowableValues}} + Self::{{ enumVars.0.name }} + {{/allowableValues}} + } +} +{{/isEnum}} +{{!-- for schemas that have a discriminator --}} +{{#discriminator}} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(tag = "{{{propertyBaseName}}}")] +pub enum {{{classname}}} { + {{^oneOf}} + {{#mappedModels}} + #[serde(rename="{{mappingName}}")] + {{{modelName}}} { + {{#vars}} + {{#description}} + /// {{{.}}} + {{/description}} + #[serde(rename = "{{{baseName}}}"{{^required}}, skip_serializing_if = "Option::is_none"{{/required}})] + {{{name}}}: {{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{^required}}Option<{{/required}}{{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{{dataType}}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{^isModel}}{{{dataType}}}{{/isModel}}{{/isEnum}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^required}}>{{/required}}, + {{/vars}} + }, + {{/mappedModels}} + {{/oneOf}} + {{^oneOf.isEmpty}} + {{#composedSchemas.oneOf}} + {{#description}} + /// {{{.}}} + {{/description}} + {{#baseName}} + #[serde(rename="{{{.}}}")] + {{/baseName}} + {{{name}}}({{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{/isModel}}{{{dataType}}}{{#isModel}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}), + {{/composedSchemas.oneOf}} + {{/oneOf.isEmpty}} +} + +impl Default for {{classname}} { + fn default() -> Self { + {{^oneOf}}{{#mappedModels}}{{#-first}}Self::{{modelName}} { + {{#vars}} + {{{name}}}: Default::default(), + {{/vars}} + }{{/-first}}{{/mappedModels}} + {{/oneOf}}{{^oneOf.isEmpty}}{{#composedSchemas.oneOf}}{{#-first}}Self::{{{name}}}(Default::default()){{/-first}}{{/composedSchemas.oneOf}}{{/oneOf.isEmpty}} + } +} + +{{/discriminator}} +{{!-- for non-enum schemas --}} +{{^isEnum}} +{{^discriminator}} +{{#vendorExtensions.x-rust-has-byte-array}}#[serde_as] +{{/vendorExtensions.x-rust-has-byte-array}}{{#oneOf.isEmpty}}#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct {{{classname}}} { +{{#vars}} + {{#description}} + /// {{{.}}} + {{/description}} + {{#isByteArray}} + {{#vendorExtensions.isMandatory}}#[serde_as(as = "serde_with::base64::Base64")]{{/vendorExtensions.isMandatory}}{{^vendorExtensions.isMandatory}}#[serde_as(as = "{{^serdeAsDoubleOption}}Option{{/serdeAsDoubleOption}}{{#serdeAsDoubleOption}}super::DoubleOption{{/serdeAsDoubleOption}}")]{{/vendorExtensions.isMandatory}} + {{/isByteArray}} + #[serde(rename = "{{{baseName}}}"{{^required}}{{#isNullable}}, default{{^isByteArray}}, with = "::serde_with::rust::double_option"{{/isByteArray}}{{/isNullable}}{{/required}}{{^required}}, skip_serializing_if = "Option::is_none"{{/required}}{{#required}}{{#isNullable}}, deserialize_with = "Option::deserialize"{{/isNullable}}{{/required}})] + pub {{{name}}}: {{! + ### Option Start + }}{{#isNullable}}Option<{{/isNullable}}{{^required}}Option<{{/required}}{{! + ### Enums + }}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{! + ### Non-Enums Start + }}{{^isEnum}}{{! + ### Models + }}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{{dataType}}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{! + ### Primative datatypes + }}{{^isModel}}{{#isByteArray}}Vec{{/isByteArray}}{{^isByteArray}}{{{dataType}}}{{/isByteArray}}{{/isModel}}{{! + ### Non-Enums End + }}{{/isEnum}}{{! + ### Option End (and trailing comma) + }}{{#isNullable}}>{{/isNullable}}{{^required}}>{{/required}}, +{{/vars}} +} + +impl {{{classname}}} { + {{#description}} + /// {{{.}}} + {{/description}} + pub fn new({{#requiredVars}}{{{name}}}: {{! + ### Option Start + }}{{#isNullable}}Option<{{/isNullable}}{{! + ### Enums + }}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{! + ### Non-Enums + }}{{^isEnum}}{{#isByteArray}}Vec{{/isByteArray}}{{^isByteArray}}{{{dataType}}}{{/isByteArray}}{{/isEnum}}{{! + ### Option End + }}{{#isNullable}}>{{/isNullable}}{{! + ### Comma for next arguement + }}{{^-last}}, {{/-last}}{{/requiredVars}}) -> {{{classname}}} { + {{{classname}}} { + {{#vars}} + {{{name}}}{{^required}}: None{{/required}}{{#required}}{{#isModel}}{{^avoidBoxedModels}}: {{^isNullable}}Box::new({{{name}}}){{/isNullable}}{{#isNullable}}if let Some(x) = {{{name}}} {Some(Box::new(x))} else {None}{{/isNullable}}{{/avoidBoxedModels}}{{/isModel}}{{/required}}, + {{/vars}} + } + } +} +{{/oneOf.isEmpty}} +{{^oneOf.isEmpty}} +{{! TODO: add other vars that are not part of the oneOf}} +{{#description}} +/// {{{.}}} +{{/description}} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum {{classname}} { +{{#composedSchemas.oneOf}} + {{#description}} + /// {{{.}}} + {{/description}} + {{{name}}}({{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{/isModel}}{{{dataType}}}{{#isModel}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}), +{{/composedSchemas.oneOf}} +} + +impl Default for {{classname}} { + fn default() -> Self { + {{#composedSchemas.oneOf}}{{#-first}}Self::{{{name}}}(Default::default()){{/-first}}{{/composedSchemas.oneOf}} + } +} +{{/oneOf.isEmpty}} +{{/discriminator}} +{{/isEnum}} +{{!-- for properties that are of enum type --}} +{{#vars}} +{{#isEnum}} +{{#description}} +/// {{{description}}} +{{/description}} +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum {{{enumName}}} { +{{#allowableValues}} +{{#enumVars}} + #[serde(rename = "{{{value}}}")] + {{{name}}}, +{{/enumVars}} +{{/allowableValues}} +} + +impl Default for {{{enumName}}} { + fn default() -> {{{enumName}}} { + {{#allowableValues}} + Self::{{ enumVars.0.name }} + {{/allowableValues}} + } +} +{{/isEnum}} +{{/vars}} + +{{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/api.mustache b/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/api.mustache new file mode 100644 index 00000000000..35f21d31b2c --- /dev/null +++ b/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/api.mustache @@ -0,0 +1,474 @@ +{{>partial_header}} + +use reqwest; +use serde::{Deserialize, Serialize, de::Error as _}; +use crate::{apis::ResponseContent, models}; +use super::{Error, configuration, ContentType}; +{{#supportWasm}} +use alloc::borrow::{Cow, ToOwned}; +use alloc::boxed::Box; +use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList}; +use alloc::rc::Rc; +use alloc::string::{String, ToString}; +use alloc::sync::Arc; +use alloc::vec::Vec; +use alloc::{fmt, format, vec}; +use wasm_std::{error, io}; +{{/supportWasm}} + +{{#operations}} +{{#operation}} +{{#vendorExtensions.x-group-parameters}} +{{#allParams}} +{{#-first}} +/// struct for passing parameters to the method [`{{operationId}}`] +#[derive(Clone, Debug)] +pub struct {{{operationIdCamelCase}}}Params { +{{/-first}} + {{#description}} + /// {{{.}}} + {{/description}} + pub {{{paramName}}}: {{! + ### Option Start + }}{{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{! + ### &str and Vec<&str> + }}{{^isUuid}}{{#isString}}{{#isArray}}Vec<{{/isArray}}String{{#isArray}}>{{/isArray}}{{/isString}}{{/isUuid}}{{! + ### UUIDs + }}{{#isUuid}}{{#isArray}}Vec<{{/isArray}}String{{#isArray}}>{{/isArray}}{{/isUuid}}{{! + ### Models and primative types + }}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{! + ### Option End + }}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{! + ### Comma for next arguement + }}{{^-last}},{{/-last}} +{{#-last}} +} + +{{/-last}} +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{/operation}} +{{/operations}} + +{{#supportMultipleResponses}} +{{#operations}} +{{#operation}} +/// struct for typed successes of method [`{{operationId}}`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum {{{operationIdCamelCase}}}Success { + {{#responses}} + {{#is2xx}} + Status{{code}}({{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}), + {{/is2xx}} + {{#is3xx}} + Status{{code}}({{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}), + {{/is3xx}} + {{/responses}} + UnknownValue(serde_json::Value), +} + +{{/operation}} +{{/operations}} +{{/supportMultipleResponses}} +{{#operations}} +{{#operation}} +/// struct for typed errors of method [`{{operationId}}`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum {{{operationIdCamelCase}}}Error { + {{#responses}} + {{#is4xx}} + Status{{code}}({{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}), + {{/is4xx}} + {{#is5xx}} + Status{{code}}({{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}), + {{/is5xx}} + {{#isDefault}} + DefaultResponse({{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}), + {{/isDefault}} + {{/responses}} + UnknownValue(serde_json::Value), +} + +{{/operation}} +{{/operations}} + +{{#operations}} +{{#operation}} +{{#description}} +/// {{{.}}} +{{/description}} +{{#notes}} +/// {{{.}}} +{{/notes}} +{{#vendorExtensions.x-group-parameters}} +pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}(configuration: &configuration::Configuration{{#allParams}}{{#-first}}, {{! +### Params +}}params: {{{operationIdCamelCase}}}Params{{/-first}}{{/allParams}}{{! +### Function return type +}}) -> Result<{{! +### Response File Support +}}{{#isResponseFile}}{{#supportAsync}}reqwest::Response{{/supportAsync}}{{^supportAsync}}reqwest::blocking::Response{{/supportAsync}}{{/isResponseFile}}{{! +### Regular Responses +}}{{^isResponseFile}}{{! +### Multi response support +}}{{#supportMultipleResponses}}ResponseContent<{{{operationIdCamelCase}}}Success>{{/supportMultipleResponses}}{{! +### Regular return type +}}{{^supportMultipleResponses}}{{^returnType}}(){{/returnType}}{{{returnType}}}{{/supportMultipleResponses}}{{/isResponseFile}}{{! +### Error Type +}}, Error<{{{operationIdCamelCase}}}Error>> { +{{/vendorExtensions.x-group-parameters}} +{{^vendorExtensions.x-group-parameters}} +pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}(configuration: &configuration::Configuration, {{#allParams}}{{{paramName}}}: {{! +### Option Start +}}{{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{! +### &str and Vec<&str> +}}{{#isString}}{{#isArray}}Vec<{{/isArray}}{{^isUuid}}&str{{/isUuid}}{{#isArray}}>{{/isArray}}{{/isString}}{{! +### UUIDs +}}{{#isUuid}}{{#isArray}}Vec<{{/isArray}}&str{{#isArray}}>{{/isArray}}{{/isUuid}}{{! +### Models and primative types +}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{! +### Option End +}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{! +### Comma for next arguement +}}{{^-last}}, {{/-last}}{{/allParams}}{{! +### Function return type +}}) -> Result<{{! +### Response File Support +}}{{#isResponseFile}}{{#supportAsync}}reqwest::Response{{/supportAsync}}{{^supportAsync}}reqwest::blocking::Response{{/supportAsync}}{{/isResponseFile}}{{! +### Regular Responses +}}{{^isResponseFile}}{{! +### Multi response support +}}{{#supportMultipleResponses}}ResponseContent<{{{operationIdCamelCase}}}Success>{{/supportMultipleResponses}}{{! +### Regular return type +}}{{^supportMultipleResponses}}{{^returnType}}(){{/returnType}}{{{returnType}}}{{/supportMultipleResponses}}{{/isResponseFile}}{{! +### Error Type +}}, Error<{{{operationIdCamelCase}}}Error>> { + {{#allParams.0}} + // add a prefix to parameters to efficiently prevent name collisions + {{/allParams.0}} + {{#allParams}} + let {{{vendorExtensions.x-rust-param-identifier}}} = {{{paramName}}}; + {{/allParams}} +{{/vendorExtensions.x-group-parameters}} + + let uri_str = format!("{}{{{path}}}", configuration.base_path{{#pathParams}}, {{{baseName}}}={{#isString}}crate::apis::urlencode({{/isString}}{{{vendorExtensions.x-rust-param-identifier}}}{{^required}}.unwrap(){{/required}}{{#required}}{{#isNullable}}.unwrap(){{/isNullable}}{{/required}}{{#isArray}}.join(",").as_ref(){{/isArray}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}.to_string(){{/isContainer}}{{/isPrimitiveType}}{{/isUuid}}{{/isString}}{{#isString}}){{/isString}}{{/pathParams}}); + let mut req_builder = configuration.client.request(reqwest::Method::{{{httpMethod}}}, &uri_str); + + {{#queryParams}} + {{#required}} + {{#isArray}} + req_builder = match "{{collectionFormat}}" { + "multi" => req_builder.query(&{{{vendorExtensions.x-rust-param-identifier}}}.into_iter().map(|p| ("{{{baseName}}}".to_owned(), p.to_string())).collect::>()), + _ => req_builder.query(&[("{{{baseName}}}", &{{{vendorExtensions.x-rust-param-identifier}}}.into_iter().map(|p| p.to_string()).collect::>().join(",").to_string())]), + }; + {{/isArray}} + {{^isArray}} + {{^isNullable}} + req_builder = req_builder.query(&[("{{{baseName}}}", &{{{vendorExtensions.x-rust-param-identifier}}}.to_string())]); + {{/isNullable}} + {{#isNullable}} + {{#isDeepObject}} + if let Some(ref param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + let params = crate::apis::parse_deep_object("{{{baseName}}}", param_value); + req_builder = req_builder.query(¶ms); + }; + {{/isDeepObject}} + {{^isDeepObject}} + if let Some(ref param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + req_builder = req_builder.query(&[("{{{baseName}}}", ¶m_value.to_string())]); + }; + {{/isDeepObject}} + {{/isNullable}} + {{/isArray}} + {{/required}} + {{^required}} + if let Some(ref param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + {{#isArray}} + req_builder = match "{{collectionFormat}}" { + "multi" => req_builder.query(¶m_value.into_iter().map(|p| ("{{{baseName}}}".to_owned(), p.to_string())).collect::>()), + _ => req_builder.query(&[("{{{baseName}}}", ¶m_value.into_iter().map(|p| p.to_string()).collect::>().join(",").to_string())]), + }; + {{/isArray}} + {{^isArray}} + {{#isDeepObject}} + let params = crate::apis::parse_deep_object("{{{baseName}}}", param_value); + req_builder = req_builder.query(¶ms); + {{/isDeepObject}} + {{^isDeepObject}} + req_builder = req_builder.query(&[("{{{baseName}}}", ¶m_value.to_string())]); + {{/isDeepObject}} + {{/isArray}} + } + {{/required}} + {{/queryParams}} + {{#hasAuthMethods}} + {{#authMethods}} + {{#isApiKey}} + {{#isKeyInQuery}} + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.query(&[("{{{keyParamName}}}", value)]); + } + {{/isKeyInQuery}} + {{/isApiKey}} + {{/authMethods}} + {{/hasAuthMethods}} + {{#hasAuthMethods}} + {{#withAWSV4Signature}} + if let Some(ref aws_v4_key) = configuration.aws_v4_key { + let new_headers = match aws_v4_key.sign( + &uri_str, + "{{{httpMethod}}}", + {{#hasBodyParam}} + {{#bodyParams}} + &serde_json::to_string(&{{{vendorExtensions.x-rust-param-identifier}}}).expect("param should serialize to string"), + {{/bodyParams}} + {{/hasBodyParam}} + {{^hasBodyParam}} + "", + {{/hasBodyParam}} + ) { + Ok(new_headers) => new_headers, + Err(err) => return Err(Error::AWSV4SignatureError(err)), + }; + for (name, value) in new_headers.iter() { + req_builder = req_builder.header(name.as_str(), value.as_str()); + } + } + {{/withAWSV4Signature}} + {{/hasAuthMethods}} + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + {{#hasHeaderParams}} + {{#headerParams}} + {{#required}} + {{^isNullable}} + req_builder = req_builder.header("{{{baseName}}}", {{{vendorExtensions.x-rust-param-identifier}}}{{#isArray}}.join(","){{/isArray}}.to_string()); + {{/isNullable}} + {{#isNullable}} + match {{{vendorExtensions.x-rust-param-identifier}}} { + Some(param_value) => { req_builder = req_builder.header("{{{baseName}}}", param_value{{#isArray}}.join(","){{/isArray}}.to_string()); }, + None => { req_builder = req_builder.header("{{{baseName}}}", ""); }, + } + {{/isNullable}} + {{/required}} + {{^required}} + if let Some(param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + req_builder = req_builder.header("{{{baseName}}}", param_value{{#isArray}}.join(","){{/isArray}}.to_string()); + } + {{/required}} + {{/headerParams}} + {{/hasHeaderParams}} + {{#hasAuthMethods}} + {{#authMethods}} + {{#supportTokenSource}} + // Obtain a token from source provider. + // Tokens can be Id or access tokens depending on the provider type and configuration. + let token = configuration.token_source.token().await.map_err(Error::TokenSource)?; + // The token format is the responsibility of the provider, thus we just set the authorization header with whatever is given. + req_builder = req_builder.header(reqwest::header::AUTHORIZATION, token); + {{/supportTokenSource}} + {{^supportTokenSource}} + {{#isApiKey}} + {{#isKeyInHeader}} + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("{{{keyParamName}}}", value); + }; + {{/isKeyInHeader}} + {{/isApiKey}} + {{#isBasic}} + {{#isBasicBasic}} + if let Some(ref auth_conf) = configuration.basic_auth { + req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned()); + }; + {{/isBasicBasic}} + {{#isBasicBearer}} + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + {{/isBasicBearer}} + {{/isBasic}} + {{#isOAuth}} + if let Some(ref token) = configuration.oauth_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + {{/isOAuth}} + {{/supportTokenSource}} + {{/authMethods}} + {{/hasAuthMethods}} + {{#isMultipart}} + {{#hasFormParams}} + let mut multipart_form = reqwest{{^supportAsync}}::blocking{{/supportAsync}}::multipart::Form::new(); + {{#formParams}} + {{#isFile}} + {{^supportAsync}} + {{#required}} + {{^isNullable}} + multipart_form = multipart_form.file("{{{baseName}}}", {{{vendorExtensions.x-rust-param-identifier}}})?; + {{/isNullable}} + {{#isNullable}} + match {{{vendorExtensions.x-rust-param-identifier}}} { + Some(param_value) => { multipart_form = multipart_form.file("{{{baseName}}}", param_value)?; }, + None => { unimplemented!("Required nullable form file param not supported"); }, + } + {{/isNullable}} + {{/required}} + {{^required}} + if let Some(param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + multipart_form = multipart_form.file("{{{baseName}}}", param_value)?; + } + {{/required}} + {{/supportAsync}} + {{#supportAsync}} + // TODO: support file upload for '{{{baseName}}}' parameter + {{/supportAsync}} + {{/isFile}} + {{^isFile}} + {{#required}} + {{^isNullable}} + multipart_form = multipart_form.text("{{{baseName}}}", {{{vendorExtensions.x-rust-param-identifier}}}{{#isArray}}.into_iter().map(|p| p.to_string()).collect::>().join(","){{/isArray}}.to_string()); + {{/isNullable}} + {{#isNullable}} + match {{{vendorExtensions.x-rust-param-identifier}}} { + Some(param_value) => { multipart_form = multipart_form.text("{{{baseName}}}", param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::>().join(","){{/isArray}}.to_string()); }, + None => { multipart_form = multipart_form.text("{{{baseName}}}", ""); }, + } + {{/isNullable}} + {{/required}} + {{^required}} + if let Some(param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + multipart_form = multipart_form.text("{{{baseName}}}", param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::>().join(","){{/isArray}}.to_string()); + } + {{/required}} + {{/isFile}} + {{/formParams}} + req_builder = req_builder.multipart(multipart_form); + {{/hasFormParams}} + {{/isMultipart}} + {{^isMultipart}} + {{#hasFormParams}} + let mut multipart_form_params = std::collections::HashMap::new(); + {{#formParams}} + {{#isFile}} + {{#required}} + {{^isNullable}} + multipart_form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content")); + {{/isNullable}} + {{#isNullable}} + match {{{vendorExtensions.x-rust-param-identifier}}} { + Some(param_value) => { multipart_form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content")); }, + None => { unimplemented!("Required nullable file form param not supported with x-www-form-urlencoded content"); }, + } + {{/isNullable}} + {{/required}} + {{^required}} + if let Some(param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + multipart_form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content")); + } + {{/required}} + {{/isFile}} + {{^isFile}} + {{#required}} + {{^isNullable}} + multipart_form_params.insert("{{{baseName}}}", {{{vendorExtensions.x-rust-param-identifier}}}{{#isArray}}.into_iter().map(|p| p.to_string()).collect::>().join(","){{/isArray}}.to_string()); + {{/isNullable}} + {{#isNullable}} + match {{{vendorExtensions.x-rust-param-identifier}}} { + Some(param_value) => { multipart_form_params.insert("{{{baseName}}}", param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::>().join(","){{/isArray}}.to_string()); }, + None => { multipart_form_params.insert("{{{baseName}}}", ""); }, + } + {{/isNullable}} + {{/required}} + {{^required}} + if let Some(param_value) = {{{vendorExtensions.x-rust-param-identifier}}} { + multipart_form_params.insert("{{{baseName}}}", param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::>().join(","){{/isArray}}.to_string()); + } + {{/required}} + {{/isFile}} + {{/formParams}} + req_builder = req_builder.form(&multipart_form_params); + {{/hasFormParams}} + {{/isMultipart}} + {{#hasBodyParam}} + {{#bodyParams}} + {{#isFile}} + req_builder = req_builder.body({{{vendorExtensions.x-rust-param-identifier}}}); + {{/isFile}} + {{^isFile}} + req_builder = req_builder.json(&{{{vendorExtensions.x-rust-param-identifier}}}); + {{/isFile}} + {{/bodyParams}} + {{/hasBodyParam}} + + let req = req_builder.build()?; + let resp = configuration.client.execute(req){{#supportAsync}}.await{{/supportAsync}}?; + + let status = resp.status(); + {{^supportMultipleResponses}} + {{^isResponseFile}} + {{#returnType}} + let content_type = resp + .headers() + .get("content-type") + .and_then(|v| v.to_str().ok()) + .unwrap_or("application/octet-stream"); + let content_type = super::ContentType::from(content_type); + {{/returnType}} + {{/isResponseFile}} + {{/supportMultipleResponses}} + + if !status.is_client_error() && !status.is_server_error() { + {{^supportMultipleResponses}} + {{#isResponseFile}} + Ok(resp) + {{/isResponseFile}} + {{^isResponseFile}} + {{^returnType}} + Ok(()) + {{/returnType}} + {{#returnType}} + let content = resp.text(){{#supportAsync}}.await{{/supportAsync}}?; + match content_type { + ContentType::Json => serde_json::from_str(&content).map_err(Error::from), + {{#vendorExtensions.x-supports-plain-text}} + ContentType::Text => Ok(content), + {{/vendorExtensions.x-supports-plain-text}} + {{^vendorExtensions.x-supports-plain-text}} + ContentType::Text => Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `{{returnType}}`"))), + {{/vendorExtensions.x-supports-plain-text}} + ContentType::Unsupported(unknown_type) => Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `{{returnType}}`")))), + } + {{/returnType}} + {{/isResponseFile}} + {{/supportMultipleResponses}} + {{#supportMultipleResponses}} + {{#isResponseFile}} + Ok(resp) + {{/isResponseFile}} + {{^isResponseFile}} + let content = resp.text(){{#supportAsync}}.await{{/supportAsync}}?; + let entity: Option<{{{operationIdCamelCase}}}Success> = serde_json::from_str(&content).ok(); + Ok(ResponseContent { status, content, entity }) + {{/isResponseFile}} + {{/supportMultipleResponses}} + } else { + let content = resp.text(){{#supportAsync}}.await{{/supportAsync}}?; + let entity: Option<{{{operationIdCamelCase}}}Error> = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { status, content, entity })) + } +} + +{{/operation}} +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/api_mod.mustache b/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/api_mod.mustache new file mode 100644 index 00000000000..d2e17f48973 --- /dev/null +++ b/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/api_mod.mustache @@ -0,0 +1,208 @@ +{{^supportWasm}} +use std::error; +use std::fmt; +{{/supportWasm}} +{{#supportWasm}} +use alloc::borrow::{Cow, ToOwned}; +use alloc::boxed::Box; +use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList}; +use alloc::rc::Rc; +use alloc::string::{String, ToString}; +use alloc::sync::Arc; +use alloc::vec::Vec; +use alloc::{fmt, format, vec}; +use wasm_std::{error, io}; +{{/supportWasm}} +{{#withAWSV4Signature}} +use aws_sigv4; +{{/withAWSV4Signature}} + +#[derive(Debug, Clone)] +pub struct ResponseContent { + pub status: reqwest::StatusCode, + pub content: String, + pub entity: Option, +} + +#[derive(Debug)] +pub enum Error { + Reqwest(reqwest::Error), + {{#supportMiddleware}} + ReqwestMiddleware(reqwest_middleware::Error), + {{/supportMiddleware}} + Serde(serde_json::Error), + Io({{^supportWasm}}std::{{/supportWasm}}io::Error), + ResponseError(ResponseContent), + {{#withAWSV4Signature}} + AWSV4SignatureError(aws_sigv4::http_request::Error), + {{/withAWSV4Signature}} + {{#supportAsync}} + {{#supportTokenSource}} + TokenSource(Box), + {{/supportTokenSource}} + {{/supportAsync}} +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (module, e) = match self { + Error::Reqwest(e) => ("reqwest", e.to_string()), + {{#supportMiddleware}} + Error::ReqwestMiddleware(e) => ("reqwest-middleware", e.to_string()), + {{/supportMiddleware}} + Error::Serde(e) => ("serde", e.to_string()), + Error::Io(e) => ("IO", e.to_string()), + Error::ResponseError(e) => ("response", format!("status code {}", e.status)), + {{#withAWSV4Signature}} + Error::AWSV4SignatureError(e) => ("aws v4 signature", e.to_string()), + {{/withAWSV4Signature}} + {{#supportAsync}} + {{#supportTokenSource}} + Error::TokenSource(e) => ("token source failure", e.to_string()), + {{/supportTokenSource}} + {{/supportAsync}} + }; + write!(f, "error in {}: {}", module, e) + } +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + Error::Io(e) => Some(e), + {{^supportWasm}} + Error::Reqwest(e) => Some(e), + {{#supportMiddleware}} + Error::ReqwestMiddleware(e) => Some(e), + {{/supportMiddleware}} + Error::Serde(e) => Some(e), + Error::ResponseError(_) => return None, + {{#withAWSV4Signature}} + Error::AWSV4SignatureError(_) => return None, + {{/withAWSV4Signature}} + {{#supportAsync}} + {{#supportTokenSource}} + Error::TokenSource(e) => Some(&**e), + {{/supportTokenSource}} + {{/supportAsync}} + {{/supportWasm}} + {{#supportWasm}} + _ => None, + {{/supportWasm}} + } + } + + fn description(&self) -> &str { + match self { + Error::Io(e) => e.description(), + {{^supportWasm}} + Error::Reqwest(e) => e.description(), + {{#supportMiddleware}} + Error::ReqwestMiddleware(e) => e.description(), + {{/supportMiddleware}} + Error::Serde(e) => e.description(), + Error::ResponseError(e) => e.description(), + {{#withAWSV4Signature}} + Error::AWSV4SignatureError(e) => e.description(), + {{/withAWSV4Signature}} + {{#supportAsync}} + {{#supportTokenSource}} + Error::TokenSource(e) => (&**e).description(), + {{/supportTokenSource}} + {{/supportAsync}} + {{/supportWasm}} + {{#supportWasm}} + _ => "unknown error", + {{/supportWasm}} + + } + } +} + +impl From for Error { + fn from(e: reqwest::Error) -> Self { + Error::Reqwest(e) + } +} + +{{#supportMiddleware}} +impl From for Error { + fn from(e: reqwest_middleware::Error) -> Self { + Error::ReqwestMiddleware(e) + } +} + +{{/supportMiddleware}} +impl From for Error { + fn from(e: serde_json::Error) -> Self { + Error::Serde(e) + } +} + +impl From<{{^supportWasm}}std::{{/supportWasm}}io::Error> for Error { + fn from(e: {{^supportWasm}}std::{{/supportWasm}}io::Error) -> Self { + Error::Io(e) + } +} + +pub fn urlencode>(s: T) -> String { + ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect() +} + +pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> { + if let serde_json::Value::Object(object) = value { + let mut params = vec![]; + + for (key, value) in object { + match value { + serde_json::Value::Object(_) => params.append(&mut parse_deep_object( + &format!("{}[{}]", prefix, key), + value, + )), + serde_json::Value::Array(array) => { + for (i, value) in array.iter().enumerate() { + params.append(&mut parse_deep_object( + &format!("{}[{}][{}]", prefix, key, i), + value, + )); + } + }, + serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())), + _ => params.push((format!("{}[{}]", prefix, key), value.to_string())), + } + } + + return params; + } + + unimplemented!("Only objects are supported with style=deepObject") +} + +/// Internal use only +/// A content type supported by this client. +#[allow(dead_code)] +enum ContentType { + Json, + Text, + Unsupported(String) +} + +impl From<&str> for ContentType { + fn from(content_type: &str) -> Self { + if content_type.starts_with("application") && content_type.contains("json") { + Self::Json + } else if content_type.starts_with("text/plain") { + Self::Text + } else { + Self::Unsupported(content_type.to_string()) + } + } +} + +{{#apiInfo}} +{{#apis}} +pub mod {{{classFilename}}}; +{{/apis}} +{{/apiInfo}} + +pub mod configuration; diff --git a/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/configuration.mustache b/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/configuration.mustache new file mode 100644 index 00000000000..ace284fe5a7 --- /dev/null +++ b/modules/openapi-generator/src/main/resources-override/rust-wasm/reqwest/configuration.mustache @@ -0,0 +1,137 @@ +{{>partial_header}} + +{{#supportWasm}} +use alloc::borrow::{Cow, ToOwned}; +use alloc::boxed::Box; +use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList}; +use alloc::rc::Rc; +use alloc::string::{String, ToString}; +use alloc::sync::Arc; +use alloc::vec::Vec; +use alloc::{fmt, format, vec}; +use wasm_std::{error, io}; +{{/supportWasm}} +{{#withAWSV4Signature}} +{{^supportWasm}} +use std::time::SystemTime; +{{/supportWasm}} +use aws_sigv4::http_request::{sign, SigningSettings, SigningParams, SignableRequest}; +use http; +use secrecy::{SecretString, ExposeSecret}; +{{/withAWSV4Signature}} +{{#supportTokenSource}} +{{^supportWasm}} +use std::sync::Arc; +{{/supportWasm}} +use google_cloud_token::TokenSource; +use async_trait::async_trait; +{{/supportTokenSource}} + +#[derive(Debug, Clone)] +pub struct Configuration { + pub base_path: String, + pub user_agent: Option, + pub client: {{#supportMiddleware}}reqwest_middleware::ClientWithMiddleware{{/supportMiddleware}}{{^supportMiddleware}}reqwest{{^supportAsync}}::blocking{{/supportAsync}}::Client{{/supportMiddleware}}, + {{^supportTokenSource}} + pub basic_auth: Option, + pub oauth_access_token: Option, + pub bearer_access_token: Option, + pub api_key: Option, + {{/supportTokenSource}} + {{#withAWSV4Signature}} + pub aws_v4_key: Option, + {{/withAWSV4Signature}} + {{#supportAsync}} + {{#supportTokenSource}} + pub token_source: Arc, + {{/supportTokenSource}} + {{/supportAsync}} +} +{{^supportTokenSource}} + +pub type BasicAuth = (String, Option); + +#[derive(Debug, Clone)] +pub struct ApiKey { + pub prefix: Option, + pub key: String, +} +{{/supportTokenSource}} + +{{#withAWSV4Signature}} +#[derive(Debug, Clone)] +pub struct AWSv4Key { + pub access_key: String, + pub secret_key: SecretString, + pub region: String, + pub service: String, +} + +impl AWSv4Key { + pub fn sign(&self, uri: &str, method: &str, body: &str) -> Result, aws_sigv4::http_request::Error> { + let request = http::Request::builder() + .uri(uri) + .method(method) + .body(body).unwrap(); + let signing_settings = SigningSettings::default(); + let signing_params = SigningParams::builder() + .access_key(self.access_key.as_str()) + .secret_key(self.secret_key.expose_secret().as_str()) + .region(self.region.as_str()) + .service_name(self.service.as_str()) + .time(SystemTime::now()) + .settings(signing_settings) + .build() + .unwrap(); + let signable_request = SignableRequest::from(&request); + let (mut signing_instructions, _signature) = sign(signable_request, &signing_params)?.into_parts(); + let mut additional_headers = Vec::<(String, String)>::new(); + if let Some(new_headers) = signing_instructions.take_headers() { + for (name, value) in new_headers.into_iter() { + additional_headers.push((name.expect("header should have name").to_string(), + value.to_str().expect("header value should be a string").to_string())); + } + } + Ok(additional_headers) + } +} +{{/withAWSV4Signature}} + +impl Configuration { + pub fn new() -> Configuration { + Configuration::default() + } +} + +impl Default for Configuration { + fn default() -> Self { + Configuration { + base_path: "{{{basePath}}}".to_owned(), + user_agent: {{#httpUserAgent}}Some("{{{.}}}".to_owned()){{/httpUserAgent}}{{^httpUserAgent}}Some("OpenAPI-Generator/{{{version}}}/rust".to_owned()){{/httpUserAgent}}, + client: {{#supportMiddleware}}reqwest_middleware::ClientBuilder::new(reqwest{{^supportAsync}}::blocking{{/supportAsync}}::Client::new()).build(){{/supportMiddleware}}{{^supportMiddleware}}reqwest{{^supportAsync}}::blocking{{/supportAsync}}::Client::new(){{/supportMiddleware}}, + {{^supportTokenSource}} + basic_auth: None, + oauth_access_token: None, + bearer_access_token: None, + api_key: None, + {{/supportTokenSource}} + {{#withAWSV4Signature}} + aws_v4_key: None, + {{/withAWSV4Signature}} + {{#supportTokenSource}} + token_source: Arc::new(NoopTokenSource{}), + {{/supportTokenSource}} + } + } +} +{{#supportTokenSource}} +#[derive(Debug)] +struct NoopTokenSource{} + +#[async_trait] +impl TokenSource for NoopTokenSource { + async fn token(&self) -> Result> { + panic!("This is dummy token source. You can use TokenSourceProvider from 'google_cloud_auth' crate, or any other compatible crate.") + } +} +{{/supportTokenSource}}