From b05baa838bdb8b6d7adb355d977a3d3859bb5606 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 16:10:56 +1200 Subject: [PATCH 01/13] [Rust Server] Update rust-server `cargo-config` to generate `.cargo/config.toml` (#17876) This is recommended by Rust 1.39: --- .../org/openapitools/codegen/languages/RustServerCodegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index ec9b3de2340a..d4153496e48e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -222,7 +222,7 @@ public RustServerCodegen() { */ supportingFiles.add(new SupportingFile("openapi.mustache", "api", "openapi.yaml")); supportingFiles.add(new SupportingFile("Cargo.mustache", "", "Cargo.toml")); - supportingFiles.add(new SupportingFile("cargo-config", ".cargo", "config")); + supportingFiles.add(new SupportingFile("cargo-config", ".cargo", "config.toml")); supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore")); supportingFiles.add(new SupportingFile("lib.mustache", "src", "lib.rs")); supportingFiles.add(new SupportingFile("context.mustache", "src", "context.rs")); From c555e51ca3c9fd0d2929d15b5946a9761a1df37f Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 16:21:48 +1200 Subject: [PATCH 02/13] [Rust Server] Fix spacing in `Cargo.mustache` (#17876) --- .../main/resources/rust-server/Cargo.mustache | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index cec9e012796a..18215abc19e9 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -82,7 +82,7 @@ hyper-tls = { version = "0.5", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common @@ -110,27 +110,27 @@ mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } {{/apiUsesMultipartFormData}} {{#apiUsesUuid}} -uuid = {version = "1.3.1", features = ["serde", "v4"]} +uuid = { version = "1.3.1", features = ["serde", "v4"]} {{/apiUsesUuid}} # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} +hyper = { version = "0.14", features = ["full"], optional = true } {{#apiUsesMultipartRelated}} -mime_multipart = {version = "0.5", optional = true} -hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true} +mime_multipart = { version = "0.5", optional = true } +hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true } {{/apiUsesMultipartRelated}} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +serde_ignored = { version = "0.1.1", optional = true } +url = { version = "2.1", optional = true } # Client-specific {{#usesUrlEncodedForm}} -serde_urlencoded = {version = "0.6.1", optional = true} +serde_urlencoded = { version = "0.6.1", optional = true } {{/usesUrlEncodedForm}} # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +percent-encoding = { version = "2.1.0", optional = true } +regex = { version = "1.3", optional = true } # CLI-specific anyhow = { version = "1", optional = true } From c766fac0ea75b1656902091bca50d4740b04db41 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 16:28:45 +1200 Subject: [PATCH 03/13] [Rust Server] Update dependency versions in `Cargo.mustache` (#17876) --- .../main/resources/rust-server/Cargo.mustache | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index 18215abc19e9..5fb6167b4126 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -78,24 +78,24 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } +hyper-openssl = { version = "0.10", optional = true } openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc1", features = ["serdejson", "server", "client", "tls", "tcp"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition {{#usesXml}} @@ -110,17 +110,17 @@ mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } {{/apiUsesMultipartFormData}} {{#apiUsesUuid}} -uuid = { version = "1.3.1", features = ["serde", "v4"]} +uuid = { version = "1.17.0", features = ["serde", "v4"]} {{/apiUsesUuid}} # Common between server and client features -hyper = { version = "0.14", features = ["full"], optional = true } +hyper = { version = "1.6", features = ["full"], optional = true } {{#apiUsesMultipartRelated}} mime_multipart = { version = "0.5", optional = true } hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true } {{/apiUsesMultipartRelated}} -serde_ignored = { version = "0.1.1", optional = true } -url = { version = "2.1", optional = true } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific {{#usesUrlEncodedForm}} @@ -128,34 +128,34 @@ serde_urlencoded = { version = "0.6.1", optional = true } {{/usesUrlEncodedForm}} # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = { version = "2.1.0", optional = true } -regex = { version = "1.3", optional = true } +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +tokio = { version = "1.45", features = ["rt-threaded", "macros", "stream"], optional = true } {{#apiHasDeleteMethods}} dialoguer = { version = "0.8", optional = true } {{/apiHasDeleteMethods}} # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] From 2960180f5e4bfed280ba4554bf0ef80835e740d4 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 17:12:05 +1200 Subject: [PATCH 04/13] [Rust Server] Update templates so generated client and server compile (#17876) --- .../main/resources/rust-server/Cargo.mustache | 11 +- .../main/resources/rust-server/auth.mustache | 12 +- .../main/resources/rust-server/cargo-config | 3 +- .../rust-server/client-imports.mustache | 5 +- .../resources/rust-server/client-mod.mustache | 105 +++++++++++------- .../rust-server/client-operation.mustache | 15 +-- .../client-request-body-instance.mustache | 4 +- ...lient-request-body-multipart-form.mustache | 2 +- .../resources/rust-server/context.mustache | 15 +-- .../main/resources/rust-server/lib.mustache | 10 -- .../rust-server/server-imports.mustache | 8 +- .../rust-server/server-make-service.mustache | 6 +- .../rust-server/server-operation.mustache | 28 ++--- .../server-response-body-instance.mustache | 2 +- .../rust-server/server-server_auth.mustache | 14 +-- .../server-service-footer.mustache | 2 +- .../server-service-header.mustache | 27 +++-- 17 files changed, 142 insertions(+), 127 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index 5fb6167b4126..a21e66d61eb4 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -50,7 +50,7 @@ client = [ "serde_ignored", "regex", "percent-encoding", "lazy_static", {{/hasCallbacks}} {{! Anything added to the list below, should probably be added to the callbacks list below }} - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ {{#apiUsesMultipart}} @@ -89,7 +89,7 @@ openssl = { version = "0.10", optional = true } async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "7.0.0-rc1", features = ["serdejson", "server", "client", "tls", "tcp"] } +swagger = { version = "7.0.0-rc1", features = ["serdejson", "server", "client", "tls"] } log = "0.4.27" mime = "0.3" @@ -114,7 +114,10 @@ uuid = { version = "1.17.0", features = ["serde", "v4"]} {{/apiUsesUuid}} # Common between server and client features +bytes = "1.10.1" +http-body-util = "0.1.3" hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } {{#apiUsesMultipartRelated}} mime_multipart = { version = "0.5", optional = true } hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true } @@ -126,6 +129,7 @@ url = { version = "2.5", optional = true } {{#usesUrlEncodedForm}} serde_urlencoded = { version = "0.6.1", optional = true } {{/usesUrlEncodedForm}} +tower-service = "0.3.3" # Server, and client callback-specific lazy_static = { version = "1.5", optional = true } @@ -136,8 +140,7 @@ regex = { version = "1.11", optional = true } anyhow = { version = "1", optional = true } clap-verbosity-flag = { version = "3.0", optional = true } simple_logger = { version = "5.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "1.45", features = ["rt-threaded", "macros", "stream"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } {{#apiHasDeleteMethods}} dialoguer = { version = "0.8", optional = true } {{/apiHasDeleteMethods}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/auth.mustache b/modules/openapi-generator/src/main/resources/rust-server/auth.mustache index d2b1481eeb81..804b96d8960b 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/auth.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/auth.mustache @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/cargo-config b/modules/openapi-generator/src/main/resources/rust-server/cargo-config index b8acc9c00c8c..df91f0f117f3 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/cargo-config +++ b/modules/openapi-generator/src/main/resources/rust-server/cargo-config @@ -6,7 +6,8 @@ rustflags = [ "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - "-W", "unsafe_code", # usage of `unsafe` code + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code "-W", "unused_qualifications", # detects unnecessarily qualified names diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache index d2a4b3fcc252..f5ad8c7265e1 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; {{#apiUsesMultipartFormData}} use mime::Mime; diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache index c49bdd656df7..92591f227429 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache @@ -29,8 +29,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -47,8 +47,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -60,8 +60,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -75,8 +75,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -99,8 +110,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -112,26 +123,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -155,13 +159,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -178,7 +182,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -200,7 +215,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -268,8 +294,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -331,22 +357,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } {{#apiInfo}} {{#apis}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache index a5f96e3dbfaf..a66417254d07 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache @@ -81,7 +81,7 @@ let mut request = match Request::builder() .method("{{{vendorExtensions.x-http-method}}}") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -208,9 +208,10 @@ {{/headers}} {{#dataType}} let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; {{>client-response-body-instance}} @@ -248,9 +249,9 @@ {{/responses}} code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache index f0f265a29d1d..7385b9ed0447 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache @@ -21,7 +21,7 @@ }); // Add the message body to the request object. - *request.body_mut() = Body::from(body); + *request.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); {{/x-consumes-multipart-related}} {{#x-consumes-form}} @@ -94,7 +94,7 @@ let body = serde_json::to_string(¶m_{{{paramName}}}).expect("impossible to fail to serialize"); {{/x-consumes-json}} {{/vendorExtensions}} - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); {{^required}} } {{/required}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-request-body-multipart-form.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-request-body-multipart-form.mustache index ce8869195f77..0a6c1738ce5b 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-request-body-multipart-form.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-request-body-multipart-form.mustache @@ -57,7 +57,7 @@ (body_string, multipart_header) }; - *request.body_mut() = Body::from(body_string); + *request.body_mut() = body_from_string(body_string); request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) { Ok(h) => h, diff --git a/modules/openapi-generator/src/main/resources/rust-server/context.mustache b/modules/openapi-generator/src/main/resources/rust-server/context.mustache index 061bd4fbf2d8..7672c728428c 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/context.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/context.mustache @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -46,11 +46,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +92,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache index e6d2bf190130..7232e662a3f1 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache @@ -35,10 +35,6 @@ pub use auth::{AuthenticationApi, Claims}; #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - {{#apiInfo}} {{#apis}} {{#operations}} @@ -64,8 +60,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; {{#apiInfo}} @@ -103,10 +97,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache index 1b39e6808be0..c4c489c6112d 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -27,4 +29,4 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache index 7471c9c2278c..125f8cfefb3c 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache @@ -45,11 +45,7 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = Service::new(self.api_impl.clone()){{^apiUsesMultipartFormData}};{{/apiUsesMultipartFormData}} {{#apiUsesMultipartFormData}} .multipart_form_size_limit(self.multipart_form_size_limit); diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache index 4957b65c4dc5..1702ee402f35 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache @@ -6,7 +6,7 @@ Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; {{#authMethods}} @@ -56,12 +56,12 @@ Ok(param_{{{paramName}}}) => param_{{{paramName}}}, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter {{{baseName}}}: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter {{{baseName}}}: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["{{{baseName}}}"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["{{{baseName}}}"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -89,7 +89,7 @@ Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header {{{baseName}}} - {}", err))) + .body(body_from_string(format!("Invalid header {{{baseName}}} - {}", err))) .expect("Unable to create Bad Request response for invalid header {{{baseName}}}")); }, @@ -98,7 +98,7 @@ {{#required}} return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required header {{{baseName}}}")) + .body(body_from_str("Missing required header {{{baseName}}}")) .expect("Unable to create Bad Request response for missing required header {{{baseName}}}")); {{/required}} {{^required}} @@ -139,7 +139,7 @@ Ok(param_{{{paramName}}}) => Some(param_{{{paramName}}}), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter {{{baseName}}}")), } }, @@ -150,7 +150,7 @@ Some(param_{{{paramName}}}) => param_{{{paramName}}}, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter {{{baseName}}}")) + .body(body_from_str("Missing required query parameter {{{baseName}}}")) .expect("Unable to create Bad Request response for missing query parameter {{{baseName}}}")), }; {{/required}} @@ -172,7 +172,7 @@ Ok(param_{{{paramName}}}) => Some(param_{{{paramName}}}), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter {{{baseName}}}")), } }, @@ -183,7 +183,7 @@ Some(param_{{{paramName}}}) => param_{{{paramName}}}, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter {{{baseName}}}")) + .body(body_from_str("Missing required query parameter {{{baseName}}}")) .expect("Unable to create Bad Request response for missing query parameter {{{baseName}}}")), }; {{/required}} @@ -196,7 +196,7 @@ // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { {{^vendorExtensions.x-consumes-multipart-form}} @@ -219,7 +219,7 @@ {{/allParams}} &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -281,7 +281,7 @@ Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling {{name}} header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling {{name}} header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -302,7 +302,7 @@ // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -311,7 +311,7 @@ }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } {{/vendorExtensions.x-has-request-body}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache index 9bb648c525f7..59ec1b74c8d4 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache @@ -46,5 +46,5 @@ {{/formParams}} {{/x-produces-multipart-related}} {{/vendorExtensions}} - *response.body_mut() = Body::from(body); + *response.body_mut() = body_from_string(body); {{/dataType}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-server_auth.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-server_auth.mustache index ba78eb2f3f5d..d63030b86840 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-server_auth.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-server_auth.mustache @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache index 793cd99e5cca..5f9a8f23e7c1 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache @@ -1,5 +1,5 @@ _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache index 997b5b5c9f0e..6a360152e966 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache @@ -1,7 +1,7 @@ -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -59,26 +59,31 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), + req: (Request, C), {{#apiUsesMultipartFormData}} multipart_form_size_limit: Option, {{/apiUsesMultipartFormData}} - ) -> Result, crate::ServiceError> where + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { From f6fd1be6abff6a895d02fd9e0f0849d82a63ffa1 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 17:35:10 +1200 Subject: [PATCH 05/13] [Rust Server] Get `server` example to compile (#17876) --- .../codegen/languages/RustServerCodegen.java | 1 + .../main/resources/rust-server/Cargo.mustache | 2 + .../resources/rust-server/context.mustache | 12 ++ .../rust-server/example-server-auth.mustache | 12 +- .../example-server-common.mustache | 110 ++++++++++--- .../rust-server/example-server-main.mustache | 19 +-- .../rust-server/example-server-tokio-io.rs | 147 ++++++++++++++++++ .../rust-server/server-make-service.mustache | 28 +++- 8 files changed, 290 insertions(+), 41 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/rust-server/example-server-tokio-io.rs diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index d4153496e48e..be96d83ec3ac 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -233,6 +233,7 @@ public RustServerCodegen() { supportingFiles.add(new SupportingFile("server-server_auth.mustache", "src/server", "server_auth.rs")); supportingFiles.add(new SupportingFile("client-mod.mustache", "src/client", "mod.rs")); supportingFiles.add(new SupportingFile("example-server-main.mustache", "examples/server", "main.rs")); + supportingFiles.add(new SupportingFile("example-server-tokio-io.rs", "examples/server", "tokio_io.rs")); supportingFiles.add(new SupportingFile("example-server-server.mustache", "examples/server", "server.rs")); supportingFiles.add(new SupportingFile("example-server-auth.mustache", "examples/server", "server_auth.rs")); supportingFiles.add(new SupportingFile("example-client-main.mustache", "examples/client", "main.rs")); diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index a21e66d61eb4..a63f5864e305 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -156,10 +156,12 @@ frunk-enum-core = { version = "0.3.0", optional = true } jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] +always_send = "0.1.1" clap = "4.5" env_logger = "0.11" tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/modules/openapi-generator/src/main/resources/rust-server/context.mustache b/modules/openapi-generator/src/main/resources/rust-server/context.mustache index 7672c728428c..4182d841c291 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/context.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/context.mustache @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-auth.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-auth.mustache index 7e0eac398fe9..208f69ad9469 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-auth.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-auth.mustache @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use {{{externCrateName}}}::{AuthenticationApi, Claims}; @@ -95,10 +94,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -124,8 +123,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -135,4 +134,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache index ee1167be8dcb..d91bfdd923ab 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use {{{externCrateName}}}::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + {{{externCrateName}}}::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - {{{externCrateName}}}::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -92,3 +154,11 @@ impl Server { Server{marker: PhantomData} } } + +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache index 58d6f9e2a65f..fa7aff899c9a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); - let addr = "127.0.0.1:{{{serverPort}}}"; + let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-tokio-io.rs b/modules/openapi-generator/src/main/resources/rust-server/example-server-tokio-io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-tokio-io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache index 125f8cfefb3c..b7ac9e0c4bd4 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache @@ -1,5 +1,6 @@ -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { @@ -7,10 +8,11 @@ pub struct MakeService where {{#apiUsesMultipartFormData}} multipart_form_size_limit: Option, {{/apiUsesMultipartFormData}} - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { @@ -37,7 +39,23 @@ impl MakeService where {{/apiUsesMultipartFormData}} } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { @@ -45,7 +63,7 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn call(&self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()){{^apiUsesMultipartFormData}};{{/apiUsesMultipartFormData}} {{#apiUsesMultipartFormData}} .multipart_form_size_limit(self.multipart_form_size_limit); From d1006f15be3139b3ee2d46663b60411c5c768f50 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 17:39:35 +1200 Subject: [PATCH 06/13] [Rust Server] Update `client` example to compile (#17876) --- .../rust-server/example-client-main.mustache | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache index 511739d707d1..e1e3d6a4c596 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache @@ -18,7 +18,7 @@ use {{{externCrateName}}}::{Api, ApiNoContext, Claims, Client, ContextWrapperExt {{/apis}} {{/apiInfo}} }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -41,10 +41,10 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ {{#apiInfo}} {{#apis}} {{#operations}} @@ -61,17 +61,15 @@ fn main() { ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("{{{serverHost}}}") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("{{{serverPort}}}") .help("Port to contact")) .get_matches(); @@ -106,22 +104,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -141,7 +139,7 @@ fn main() { rt.spawn(server::create("127.0.0.1:8081", false)); {{/hasCallbacks}} - match matches.value_of("operation") { + match matches.get_one::("operation") { {{#apiInfo}} {{#apis}} {{#operations}} From 5fcecae13564239bc165227518a462b9ddf12a68 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Tue, 27 May 2025 18:24:35 +1200 Subject: [PATCH 07/13] [Rust Server] Update `bin/cli.rs` to compile (#17876) --- .../main/resources/rust-server/Cargo.mustache | 2 +- .../resources/rust-server/bin-cli.mustache | 42 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index a63f5864e305..a3ec3875cafa 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -72,7 +72,7 @@ cli = [ {{#apiHasDeleteMethods}} "dialoguer", {{/apiHasDeleteMethods}} - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] diff --git a/modules/openapi-generator/src/main/resources/rust-server/bin-cli.mustache b/modules/openapi-generator/src/main/resources/rust-server/bin-cli.mustache index 0406c5c12e03..0de05b75f95a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/bin-cli.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/bin-cli.mustache @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; {{#apiHasDeleteMethods}} use dialoguer::Confirm; {{/apiHasDeleteMethods}} @@ -19,7 +20,6 @@ use {{{externCrateName}}}::{ {{/apiInfo}} }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -30,65 +30,65 @@ type ClientContext = swagger::make_context_ty!( ); {{! See code in RustServerCodegen if you are adding additional short option usage here. }} -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "{{appName}}", version = "{{version}}", about = "CLI access to {{appName}}" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, {{#apiHasDeleteMethods}} /// Don't ask for any confirmation prompts #[allow(dead_code)] - #[structopt(short, long)] + #[clap(short, long)] force: bool, {{/apiHasDeleteMethods}} {{#hasHttpBearerMethods}} /// Bearer token if used for authentication - #[structopt(env = "{{#lambda.uppercase}}{{externCrateName}}{{/lambda.uppercase}}_BEARER_TOKEN", hide_env_values = true)] + #[clap(env = "{{#lambda.uppercase}}{{externCrateName}}{{/lambda.uppercase}}_BEARER_TOKEN", hide_env_values = true)] bearer_token: Option, {{/hasHttpBearerMethods}} {{^hasHttpBearerMethods}} {{#hasOAuthMethods}} /// Bearer token if used for authentication - #[structopt(env = "{{#lambda.uppercase}}{{externCrateName}}{{/lambda.uppercase}}_BEARER_TOKEN", hide_env_values = true)] + #[clap(env = "{{#lambda.uppercase}}{{externCrateName}}{{/lambda.uppercase}}_BEARER_TOKEN", hide_env_values = true)] bearer_token: Option, {{/hasOAuthMethods}} {{/hasHttpBearerMethods}} } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { {{#apiInfo}} {{#apis}} @@ -103,21 +103,21 @@ enum Operation { /// {{{description}}} {{/description}} {{^isPrimitiveType}} - #[structopt(parse(try_from_str = parse_json){{#isArray}}, long{{/isArray}})] + #[clap(value_parser = parse_json::<{{{dataType}}}>){{#isArray}}, long{{/isArray}}] {{/isPrimitiveType}} {{#isByteArray}} - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::<{{{dataType}}}>)] {{/isByteArray}} {{#isBinary}} - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::<{{{dataType}}}>)] {{/isBinary}} {{#isBoolean}} {{#isPrimitiveType}} {{#vendorExtensions.x-provide-cli-short-opt}} - #[structopt(short, long)] + #[clap(short, long)] {{/vendorExtensions.x-provide-cli-short-opt}} {{^vendorExtensions.x-provide-cli-short-opt}} - #[structopt(long)] + #[clap(long)] {{/vendorExtensions.x-provide-cli-short-opt}} {{/isPrimitiveType}} {{/isBoolean}} @@ -165,7 +165,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -312,6 +312,6 @@ fn prompt(force: bool, text: &str) -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } From fa5ef80857ab187f790aa518ab86e3a7e7b57518 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Thu, 12 Jun 2025 07:41:59 +1200 Subject: [PATCH 08/13] [Rust Server] Update `swagger` to `rc2`. --- .../src/main/resources/rust-server/Cargo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index a3ec3875cafa..6757c3650a9a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -89,7 +89,7 @@ openssl = { version = "0.10", optional = true } async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "7.0.0-rc1", features = ["serdejson", "server", "client", "tls"] } +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } log = "0.4.27" mime = "0.3" From 2552fc430a611bf0c705cac825f856c280101ea5 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Thu, 12 Jun 2025 08:16:17 +1200 Subject: [PATCH 09/13] [Rust Server] Remove `"clap"` from "cli" feature. --- .../src/main/resources/rust-server/Cargo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index 6757c3650a9a..4ef7de848d14 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -72,7 +72,7 @@ cli = [ {{#apiHasDeleteMethods}} "dialoguer", {{/apiHasDeleteMethods}} - "anyhow", "clap", "clap-verbosity-flag", "simple_logger", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] From 1dd673415ffe1bb7fee50d0304abc00948721267 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Thu, 12 Jun 2025 08:33:28 +1200 Subject: [PATCH 10/13] [Rust Server] Update more `Body` instantiations. --- .../rust-server/server-callbacks.mustache | 20 +++++++++---------- .../rust-server/server-operation.mustache | 2 +- .../server-request-body-basic.mustache | 6 +++--- ...erver-request-body-multipart-form.mustache | 16 +++++++-------- ...er-request-body-multipart-related.mustache | 8 ++++---- .../server-response-body-instance.mustache | 2 +- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache index 2c95e530895d..fb4a35476a17 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache @@ -19,8 +19,8 @@ use crate::{{{operationId}}}Response; /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, C: Clone + Send + Sync + 'static @@ -34,8 +34,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, C: Clone + Send + Sync + 'static @@ -47,8 +47,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, C: Clone + Send + Sync + 'static @@ -169,8 +169,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, C: Clone + Send + Sync + 'static @@ -191,8 +191,8 @@ impl Client where #[async_trait] impl CallbackApi for Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, S::Error: Into + fmt::Display, diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache index 1702ee402f35..a35536132924 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache @@ -24,7 +24,7 @@ let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache index 97422852ca75..2f86b9325867 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache @@ -15,7 +15,7 @@ {{#required}} Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter {{{baseName}}} - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter {{{baseName}}} - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to schema")), {{/required}} {{^required}} @@ -32,7 +32,7 @@ Ok(param_{{{paramName}}}) => Some(param_{{{paramName}}}), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter {{{baseName}}} - not valid UTF-8: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter {{{baseName}}} - not valid UTF-8: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to UTF-8")), } {{/isString}} @@ -46,7 +46,7 @@ Some(param_{{{paramName}}}) => param_{{{paramName}}}, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter {{{baseName}}}")) + .body(body_from_str("Missing required body parameter {{{baseName}}}")) .expect("Unable to create Bad Request response for missing body parameter {{{baseName}}}")), }; {{/required}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-form.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-form.mustache index f563459396a8..c70e9887c7af 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-form.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-form.mustache @@ -2,7 +2,7 @@ Some(boundary) => boundary.to_string(), None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Couldn't find valid multipart body".to_string())) + .body(body_from_str("Couldn't find valid multipart body".to_string())) .expect("Unable to create Bad Request response for incorrect boundary")), }; @@ -20,31 +20,31 @@ SaveResult::Partial(_, PartialReason::CountLimit) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to excessive parts".to_string())) + .body(body_from_str("Unable to process message part due to excessive parts".to_string())) .expect("Unable to create Bad Request response due to excessive parts")) }, SaveResult::Partial(_, PartialReason::SizeLimit) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to excessive data".to_string())) + .body(body_from_str("Unable to process message part due to excessive data".to_string())) .expect("Unable to create Bad Request response due to excessive data")) }, SaveResult::Partial(_, PartialReason::Utf8Error(_)) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to invalid data".to_string())) + .body(body_from_str("Unable to process message part due to invalid data".to_string())) .expect("Unable to create Bad Request response due to invalid data")) }, SaveResult::Partial(_, PartialReason::IoError(_)) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from("Failed to process message part due an internal error".to_string())) + .body(body_from_str("Failed to process message part due an internal error".to_string())) .expect("Unable to create Internal Server Error response due to an internal error")) }, SaveResult::Error(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from("Failed to process all message parts due to an internal error".to_string())) + .body(body_from_str("Failed to process all message parts due to an internal error".to_string())) .expect("Unable to create Internal Server Error response due to an internal error")) }, }; @@ -71,7 +71,7 @@ return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("{{{paramName}}} data does not match API definition : {}", e))) + .body(body_from_string(format!("{{{paramName}}} data does not match API definition : {}", e))) .expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}")) } }; @@ -87,7 +87,7 @@ return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required form parameter {{{paramName}}}".to_string())) + .body(body_from_str("Missing required form parameter {{{paramName}}}".to_string())) .expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}")) {{/required}} {{^required}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-related.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-related.mustache index b9dc330ef3f8..c0cd60135536 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-related.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-multipart-related.mustache @@ -6,7 +6,7 @@ Err(e) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(e)) + .body(body_from_string(e.to_string())) .expect("Unable to create Bad Request response due to unable to read content-type header for {{operationId}}")); } }; @@ -18,7 +18,7 @@ Err(e) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Could not read multipart body for {{operationId}}: {}", e))) + .body(body_from_string(format!("Could not read multipart body for {{operationId}}: {}", e))) .expect("Unable to create Bad Request response due to unable to read multipart body for {{operationId}}")); } }; @@ -43,7 +43,7 @@ Ok(json_data) => json_data, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter {{dataType}} - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter {{dataType}} - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter {{dataType}} due to schema")) }; // Push JSON part to return object. @@ -79,7 +79,7 @@ Some(x) => x, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required multipart/related parameter {{{paramName}}}".to_string())) + .body(body_from_str("Missing required multipart/related parameter {{{paramName}}}".to_string())) .expect("Unable to create Bad Request response for missing multipart/related parameter {{{paramName}}} due to schema")) }; {{/required}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache index 59ec1b74c8d4..5915e8c697f8 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-response-body-instance.mustache @@ -46,5 +46,5 @@ {{/formParams}} {{/x-produces-multipart-related}} {{/vendorExtensions}} - *response.body_mut() = body_from_string(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); {{/dataType}} From 05e3016c30d1f334c8b8ee6ed8e6fb7d36356781 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Thu, 12 Jun 2025 08:43:03 +1200 Subject: [PATCH 11/13] [Rust Server] Add `Has>` bounds on `C`. --- .../rust-server/server-callbacks.mustache | 14 +++++++------- .../rust-server/server-make-service.mustache | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache index fb4a35476a17..3501b6735f53 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache @@ -23,7 +23,7 @@ pub struct Client where Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Inner service client_service: S, @@ -38,7 +38,7 @@ impl fmt::Debug for Client where Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client") @@ -51,7 +51,7 @@ impl Clone for Client where Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { fn clone(&self) -> Self { Self { @@ -63,7 +63,7 @@ impl Clone for Client where impl Client, C>, C> where Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -90,7 +90,7 @@ impl Client Client, C>, C> where - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Create an HTTP client. pub fn new_http() -> Self { @@ -106,7 +106,7 @@ type HttpsConnector = hyper_tls::HttpsConnector; type HttpsConnector = hyper_openssl::HttpsConnector; impl Client, C>, C> where - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Create a client with a TLS connection to the server. #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -173,7 +173,7 @@ impl Client where Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` /// diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache index b7ac9e0c4bd4..a717d96b8301 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache @@ -42,7 +42,7 @@ where impl Clone for MakeService where T: Api + Clone + Send + 'static, - C: Has + Send + Sync + 'static + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { fn clone(&self) -> Self { Self { From 88b1ed3a3c3dfd456e205a2df071d9846428dc0c Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Thu, 12 Jun 2025 08:44:42 +1200 Subject: [PATCH 12/13] [Rust Server] Reference legacy `hyper_utils` `Client` in `server-callbacks`. --- .../main/resources/rust-server/server-callbacks.mustache | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache index 3501b6735f53..f8af02f6413b 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache @@ -61,7 +61,7 @@ impl Clone for Client where } } -impl Client, C>, C> where +impl Client>, C>, C> where Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { @@ -79,7 +79,7 @@ impl Client Self { - let client_service = hyper::client::Client::builder().build(connector); + let client_service = hyper_util::client::legacy::Client::builder().build(connector); let client_service = DropContextService::new(client_service); Self { @@ -89,7 +89,7 @@ impl Client Client, C>, C> where +impl Client>, C>, C> where C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Create an HTTP client. @@ -105,7 +105,7 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client>, C>, C> where C: Clone{{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { /// Create a client with a TLS connection to the server. From 9795e2c07dce832feaf81fee19a61a8fc2b712b9 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Thu, 12 Jun 2025 07:42:58 +1200 Subject: [PATCH 13/13] [Rust Server] Regenerate samples. --- .../.cargo/{config => config.toml} | 3 +- .../multipart-v3/.openapi-generator/FILES | 3 +- .../output/multipart-v3/Cargo.toml | 59 +- .../output/multipart-v3/bin/cli.rs | 40 +- .../multipart-v3/examples/client/main.rs | 28 +- .../multipart-v3/examples/server/main.rs | 17 +- .../multipart-v3/examples/server/server.rs | 110 +++- .../examples/server/server_auth.rs | 12 +- .../multipart-v3/examples/server/tokio_io.rs | 147 +++++ .../output/multipart-v3/src/auth.rs | 12 +- .../output/multipart-v3/src/client/mod.rs | 140 +++-- .../output/multipart-v3/src/context.rs | 27 +- .../output/multipart-v3/src/lib.rs | 10 - .../output/multipart-v3/src/server/mod.rs | 127 +++-- .../multipart-v3/src/server/server_auth.rs | 14 +- .../.cargo/{config => config.toml} | 3 +- .../no-example-v3/.openapi-generator/FILES | 3 +- .../output/no-example-v3/Cargo.toml | 55 +- .../output/no-example-v3/bin/cli.rs | 28 +- .../no-example-v3/examples/client/main.rs | 28 +- .../no-example-v3/examples/server/main.rs | 17 +- .../no-example-v3/examples/server/server.rs | 110 +++- .../examples/server/server_auth.rs | 12 +- .../no-example-v3/examples/server/tokio_io.rs | 147 +++++ .../output/no-example-v3/src/auth.rs | 12 +- .../output/no-example-v3/src/client/mod.rs | 120 ++-- .../output/no-example-v3/src/context.rs | 27 +- .../output/no-example-v3/src/lib.rs | 10 - .../output/no-example-v3/src/server/mod.rs | 81 ++- .../no-example-v3/src/server/server_auth.rs | 14 +- .../openapi-v3/.cargo/{config => config.toml} | 3 +- .../openapi-v3/.openapi-generator/FILES | 3 +- .../rust-server/output/openapi-v3/Cargo.toml | 59 +- .../rust-server/output/openapi-v3/bin/cli.rs | 66 +-- .../output/openapi-v3/examples/client/main.rs | 28 +- .../openapi-v3/examples/client/server.rs | 110 +++- .../output/openapi-v3/examples/server/main.rs | 17 +- .../openapi-v3/examples/server/server.rs | 110 +++- .../openapi-v3/examples/server/server_auth.rs | 12 +- .../openapi-v3/examples/server/tokio_io.rs | 147 +++++ .../rust-server/output/openapi-v3/src/auth.rs | 12 +- .../output/openapi-v3/src/client/callbacks.rs | 79 ++- .../output/openapi-v3/src/client/mod.rs | 506 +++++++++-------- .../output/openapi-v3/src/context.rs | 27 +- .../rust-server/output/openapi-v3/src/lib.rs | 10 - .../output/openapi-v3/src/server/callbacks.rs | 63 +- .../output/openapi-v3/src/server/mod.rs | 333 ++++++----- .../openapi-v3/src/server/server_auth.rs | 14 +- .../ops-v3/.cargo/{config => config.toml} | 3 +- .../output/ops-v3/.openapi-generator/FILES | 3 +- .../rust-server/output/ops-v3/Cargo.toml | 55 +- .../rust-server/output/ops-v3/bin/cli.rs | 26 +- .../output/ops-v3/examples/client/main.rs | 28 +- .../output/ops-v3/examples/server/main.rs | 17 +- .../output/ops-v3/examples/server/server.rs | 110 +++- .../ops-v3/examples/server/server_auth.rs | 12 +- .../output/ops-v3/examples/server/tokio_io.rs | 147 +++++ .../rust-server/output/ops-v3/src/auth.rs | 12 +- .../output/ops-v3/src/client/mod.rs | 406 ++++++------- .../rust-server/output/ops-v3/src/context.rs | 27 +- .../rust-server/output/ops-v3/src/lib.rs | 10 - .../output/ops-v3/src/server/mod.rs | 217 +++---- .../output/ops-v3/src/server/server_auth.rs | 14 +- .../.cargo/config | 18 - .../.cargo/config.toml | 19 + .../.openapi-generator/FILES | 3 +- .../Cargo.toml | 59 +- .../bin/cli.rs | 86 +-- .../examples/client/main.rs | 28 +- .../examples/server/main.rs | 19 +- .../examples/server/server.rs | 110 +++- .../examples/server/server_auth.rs | 12 +- .../examples/server/tokio_io.rs | 147 +++++ .../src/auth.rs | 12 +- .../src/client/mod.rs | 536 ++++++++++-------- .../src/context.rs | 27 +- .../src/lib.rs | 10 - .../src/server/mod.rs | 493 ++++++++-------- .../src/server/server_auth.rs | 14 +- .../output/ping-bearer-auth/.cargo/config | 18 - .../ping-bearer-auth/.cargo/config.toml | 19 + .../ping-bearer-auth/.openapi-generator/FILES | 3 +- .../output/ping-bearer-auth/Cargo.toml | 55 +- .../output/ping-bearer-auth/bin/cli.rs | 28 +- .../ping-bearer-auth/examples/client/main.rs | 28 +- .../ping-bearer-auth/examples/server/main.rs | 17 +- .../examples/server/server.rs | 110 +++- .../examples/server/server_auth.rs | 12 +- .../examples/server/tokio_io.rs | 147 +++++ .../output/ping-bearer-auth/src/auth.rs | 12 +- .../output/ping-bearer-auth/src/client/mod.rs | 118 ++-- .../output/ping-bearer-auth/src/context.rs | 27 +- .../output/ping-bearer-auth/src/lib.rs | 10 - .../output/ping-bearer-auth/src/server/mod.rs | 75 ++- .../src/server/server_auth.rs | 14 +- .../output/rust-server-test/.cargo/config | 18 - .../rust-server-test/.cargo/config.toml | 19 + .../rust-server-test/.openapi-generator/FILES | 3 +- .../output/rust-server-test/Cargo.toml | 55 +- .../output/rust-server-test/bin/cli.rs | 28 +- .../rust-server-test/examples/client/main.rs | 28 +- .../rust-server-test/examples/server/main.rs | 17 +- .../examples/server/server.rs | 110 +++- .../examples/server/server_auth.rs | 12 +- .../examples/server/tokio_io.rs | 147 +++++ .../output/rust-server-test/src/auth.rs | 12 +- .../output/rust-server-test/src/client/mod.rs | 225 ++++---- .../output/rust-server-test/src/context.rs | 27 +- .../output/rust-server-test/src/lib.rs | 10 - .../output/rust-server-test/src/server/mod.rs | 147 +++-- .../src/server/server_auth.rs | 14 +- 111 files changed, 4611 insertions(+), 2649 deletions(-) rename samples/server/petstore/rust-server/output/multipart-v3/.cargo/{config => config.toml} (82%) create mode 100644 samples/server/petstore/rust-server/output/multipart-v3/examples/server/tokio_io.rs rename samples/server/petstore/rust-server/output/no-example-v3/.cargo/{config => config.toml} (82%) create mode 100644 samples/server/petstore/rust-server/output/no-example-v3/examples/server/tokio_io.rs rename samples/server/petstore/rust-server/output/openapi-v3/.cargo/{config => config.toml} (82%) create mode 100644 samples/server/petstore/rust-server/output/openapi-v3/examples/server/tokio_io.rs rename samples/server/petstore/rust-server/output/ops-v3/.cargo/{config => config.toml} (82%) create mode 100644 samples/server/petstore/rust-server/output/ops-v3/examples/server/tokio_io.rs delete mode 100644 samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config create mode 100644 samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config.toml create mode 100644 samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/tokio_io.rs delete mode 100644 samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config create mode 100644 samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config.toml create mode 100644 samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/tokio_io.rs delete mode 100644 samples/server/petstore/rust-server/output/rust-server-test/.cargo/config create mode 100644 samples/server/petstore/rust-server/output/rust-server-test/.cargo/config.toml create mode 100644 samples/server/petstore/rust-server/output/rust-server-test/examples/server/tokio_io.rs diff --git a/samples/server/petstore/rust-server/output/multipart-v3/.cargo/config b/samples/server/petstore/rust-server/output/multipart-v3/.cargo/config.toml similarity index 82% rename from samples/server/petstore/rust-server/output/multipart-v3/.cargo/config rename to samples/server/petstore/rust-server/output/multipart-v3/.cargo/config.toml index b8acc9c00c8c..df91f0f117f3 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/.cargo/config +++ b/samples/server/petstore/rust-server/output/multipart-v3/.cargo/config.toml @@ -6,7 +6,8 @@ rustflags = [ "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - "-W", "unsafe_code", # usage of `unsafe` code + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code "-W", "unused_qualifications", # detects unnecessarily qualified names diff --git a/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator/FILES index 3f051cfa5e44..992dbc37e38e 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -16,6 +16,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/mod.rs src/context.rs diff --git a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml index c17bc7e481fd..f11408eec1e4 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml @@ -13,7 +13,7 @@ client = [ "mime_0_2", "multipart", "multipart/client", "swagger/multipart_form", "hyper_0_10", "mime_multipart", "swagger/multipart_related", - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "mime_0_2", @@ -22,71 +22,76 @@ server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] cli = [ - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -mime_multipart = {version = "0.5", optional = true} -hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +mime_multipart = { version = "0.5", optional = true } +hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/multipart-v3/bin/cli.rs b/samples/server/petstore/rust-server/output/multipart-v3/bin/cli.rs index cc14190181fb..112fcdde7e9f 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use log::{debug, info}; // models may be unused if all inputs are primitive types #[allow(unused_imports)] @@ -10,7 +11,6 @@ use multipart_v3::{ MultipleIdenticalMimeTypesPostResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -20,65 +20,65 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "Multipart OpenAPI V3 Rust Server Test", version = "1.0.7", about = "CLI access to Multipart OpenAPI V3 Rust Server Test" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { MultipartRelatedRequestPost { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] required_binary_field: swagger::ByteArray, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] object_field: Option, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] optional_binary_field: Option, }, MultipartRequestPost { string_field: String, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] binary_field: swagger::ByteArray, optional_string_field: Option, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] object_field: Option, }, MultipleIdenticalMimeTypesPost { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] binary1: Option, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] binary2: Option, }, } @@ -118,7 +118,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -210,6 +210,6 @@ async fn main() -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs index f679dbf950f6..b88e79aac495 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs @@ -9,7 +9,7 @@ use multipart_v3::{Api, ApiNoContext, Claims, Client, ContextWrapperExt, models, MultipartRequestPostResponse, MultipleIdenticalMimeTypesPostResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -32,27 +32,25 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ "MultipartRelatedRequestPost", "MultipartRequestPost", "MultipleIdenticalMimeTypesPost", ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("localhost") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("8080") .help("Port to contact")) .get_matches(); @@ -76,22 +74,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -106,7 +104,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); - match matches.value_of("operation") { + match matches.get_one::("operation") { Some("MultipartRelatedRequestPost") => { let result = rt.block_on(client.multipart_related_request_post( swagger::ByteArray(Vec::from("BINARY_DATA_HERE")), diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs index a0b4755e80c1..868353c04a46 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs index 5b2d8a75d03d..a167c6e28bc4 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use multipart_v3::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + multipart_v3::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - multipart_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server_auth.rs index bf48130e2941..93b738c6576c 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use multipart_v3::{AuthenticationApi, Claims}; @@ -84,10 +83,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -113,8 +112,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -124,4 +123,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/auth.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/auth.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs index 42a5fbc96b86..d83eddd80b55 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use mime::Mime; use std::io::Cursor; @@ -68,8 +71,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -86,8 +89,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -99,8 +102,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -114,8 +117,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -138,8 +152,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -151,26 +165,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -194,13 +201,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -217,7 +224,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -239,7 +257,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -307,8 +336,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -370,22 +399,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn multipart_related_request_post( &self, @@ -418,7 +444,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -487,7 +513,7 @@ impl Api for Client where }); // Add the message body to the request object. - *request.body_mut() = Body::from(body); + *request.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); let header = HeaderValue::from_str(Has::::get(context).0.as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { @@ -506,9 +532,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -556,7 +582,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -635,7 +661,7 @@ impl Api for Client where (body_string, multipart_header) }; - *request.body_mut() = Body::from(body_string); + *request.body_mut() = body_from_string(body_string); request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) { Ok(h) => h, @@ -660,9 +686,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -708,7 +734,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -762,7 +788,7 @@ impl Api for Client where }); // Add the message body to the request object. - *request.body_mut() = Body::from(body); + *request.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); let header = HeaderValue::from_str(Has::::get(context).0.as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { @@ -781,9 +807,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs index ee8e118587bb..826c5e146ec7 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs index 8c41db6313c6..f4d488090a01 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs @@ -42,10 +42,6 @@ pub enum MultipleIdenticalMimeTypesPostResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - async fn multipart_related_request_post( &self, required_binary_field: swagger::ByteArray, @@ -74,8 +70,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; async fn multipart_related_request_post( @@ -116,10 +110,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs index 442c54a8db74..8a93f8086f88 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -23,7 +25,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, MultipartRelatedRequestPostResponse, @@ -50,16 +52,18 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { api_impl: T, multipart_form_size_limit: Option, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -82,7 +86,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -90,11 +110,7 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()) .multipart_form_size_limit(self.multipart_form_size_limit); @@ -102,10 +118,10 @@ impl hyper::service::Service for MakeService where } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -155,24 +171,29 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), + req: (Request, C), multipart_form_size_limit: Option, - ) -> Result, crate::ServiceError> where + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -188,7 +209,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -200,7 +221,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(e)) + .body(body_from_string(e.to_string())) .expect("Unable to create Bad Request response due to unable to read content-type header for MultipartRelatedRequestPost")); } }; @@ -212,7 +233,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Could not read multipart body for MultipartRelatedRequestPost: {}", e))) + .body(body_from_string(format!("Could not read multipart body for MultipartRelatedRequestPost: {}", e))) .expect("Unable to create Bad Request response due to unable to read multipart body for MultipartRelatedRequestPost")); } }; @@ -235,7 +256,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(json_data) => json_data, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter models::MultipartRequestObjectField - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter models::MultipartRequestObjectField - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter models::MultipartRequestObjectField due to schema")) }; // Push JSON part to return object. @@ -266,7 +287,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(x) => x, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required multipart/related parameter required_binary_field".to_string())) + .body(body_from_str("Missing required multipart/related parameter required_binary_field".to_string())) .expect("Unable to create Bad Request response for missing multipart/related parameter required_binary_field due to schema")) }; @@ -277,7 +298,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_optional_binary_field, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -301,7 +322,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -309,7 +330,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -319,14 +340,14 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let boundary = match swagger::multipart::form::boundary(&headers) { Some(boundary) => boundary.to_string(), None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Couldn't find valid multipart body".to_string())) + .body(body_from_str("Couldn't find valid multipart body".to_string())) .expect("Unable to create Bad Request response for incorrect boundary")), }; @@ -344,31 +365,31 @@ impl hyper::service::Service<(Request, C)> for Service where SaveResult::Partial(_, PartialReason::CountLimit) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to excessive parts".to_string())) + .body(body_from_str("Unable to process message part due to excessive parts".to_string())) .expect("Unable to create Bad Request response due to excessive parts")) }, SaveResult::Partial(_, PartialReason::SizeLimit) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to excessive data".to_string())) + .body(body_from_str("Unable to process message part due to excessive data".to_string())) .expect("Unable to create Bad Request response due to excessive data")) }, SaveResult::Partial(_, PartialReason::Utf8Error(_)) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to invalid data".to_string())) + .body(body_from_str("Unable to process message part due to invalid data".to_string())) .expect("Unable to create Bad Request response due to invalid data")) }, SaveResult::Partial(_, PartialReason::IoError(_)) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from("Failed to process message part due an internal error".to_string())) + .body(body_from_str("Failed to process message part due an internal error".to_string())) .expect("Unable to create Internal Server Error response due to an internal error")) }, SaveResult::Error(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from("Failed to process all message parts due to an internal error".to_string())) + .body(body_from_str("Failed to process all message parts due to an internal error".to_string())) .expect("Unable to create Internal Server Error response due to an internal error")) }, }; @@ -384,7 +405,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("string_field data does not match API definition : {}", e))) + .body(body_from_string(format!("string_field data does not match API definition : {}", e))) .expect("Unable to create Bad Request due to missing required form parameter string_field")) } }; @@ -394,7 +415,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required form parameter string_field".to_string())) + .body(body_from_str("Missing required form parameter string_field".to_string())) .expect("Unable to create Bad Request due to missing required form parameter string_field")) } }; @@ -411,7 +432,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("optional_string_field data does not match API definition : {}", e))) + .body(body_from_string(format!("optional_string_field data does not match API definition : {}", e))) .expect("Unable to create Bad Request due to missing required form parameter optional_string_field")) } }; @@ -435,7 +456,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("object_field data does not match API definition : {}", e))) + .body(body_from_string(format!("object_field data does not match API definition : {}", e))) .expect("Unable to create Bad Request due to missing required form parameter object_field")) } }; @@ -458,7 +479,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required form parameter binary_field".to_string())) + .body(body_from_str("Missing required form parameter binary_field".to_string())) .expect("Unable to create Bad Request due to missing required form parameter binary_field")) } }; @@ -471,7 +492,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_object_field, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -489,7 +510,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -497,7 +518,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -507,7 +528,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -519,7 +540,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(e)) + .body(body_from_string(e.to_string())) .expect("Unable to create Bad Request response due to unable to read content-type header for MultipleIdenticalMimeTypesPost")); } }; @@ -531,7 +552,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Could not read multipart body for MultipleIdenticalMimeTypesPost: {}", e))) + .body(body_from_string(format!("Could not read multipart body for MultipleIdenticalMimeTypesPost: {}", e))) .expect("Unable to create Bad Request response due to unable to read multipart body for MultipleIdenticalMimeTypesPost")); } }; @@ -571,7 +592,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_binary2, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -595,7 +616,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -603,7 +624,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -612,7 +633,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_MULTIPART_REQUEST) => method_not_allowed(), _ if path.matched(paths::ID_MULTIPLE_IDENTICAL_MIME_TYPES) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/.cargo/config b/samples/server/petstore/rust-server/output/no-example-v3/.cargo/config.toml similarity index 82% rename from samples/server/petstore/rust-server/output/no-example-v3/.cargo/config rename to samples/server/petstore/rust-server/output/no-example-v3/.cargo/config.toml index b8acc9c00c8c..df91f0f117f3 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/.cargo/config +++ b/samples/server/petstore/rust-server/output/no-example-v3/.cargo/config.toml @@ -6,7 +6,8 @@ rustflags = [ "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - "-W", "unsafe_code", # usage of `unsafe` code + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code "-W", "unused_qualifications", # detects unnecessarily qualified names diff --git a/samples/server/petstore/rust-server/output/no-example-v3/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/no-example-v3/.openapi-generator/FILES index 7c4254323479..d12e8c3e4109 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/no-example-v3/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -14,6 +14,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/mod.rs src/context.rs diff --git a/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml b/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml index 4315116e7edf..3936497c7249 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml @@ -10,73 +10,78 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] cli = [ - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/no-example-v3/bin/cli.rs b/samples/server/petstore/rust-server/output/no-example-v3/bin/cli.rs index 1f77caa4a8f6..7e9336dfc174 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use log::{debug, info}; // models may be unused if all inputs are primitive types #[allow(unused_imports)] @@ -8,7 +9,6 @@ use no_example_v3::{ OpGetResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -18,47 +18,47 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "Regression test for an API which doesn't have any example", version = "0.0.1", about = "CLI access to Regression test for an API which doesn't have any example" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { OpGet { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] op_get_request: models::OpGetRequest, }, } @@ -98,7 +98,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -146,6 +146,6 @@ async fn main() -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs index 79405fc5d227..be193a65265f 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs @@ -7,7 +7,7 @@ use futures::{future, Stream, stream}; use no_example_v3::{Api, ApiNoContext, Claims, Client, ContextWrapperExt, models, OpGetResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -30,24 +30,22 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("localhost") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("8080") .help("Port to contact")) .get_matches(); @@ -71,22 +69,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -101,7 +99,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); - match matches.value_of("operation") { + match matches.get_one::("operation") { /* Disabled because there's no example. Some("OpGet") => { let result = rt.block_on(client.op_get( diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs index ae01015501e5..0e749f5eee09 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs index c4e6006fb34e..49d56813ef1e 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use no_example_v3::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + no_example_v3::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - no_example_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server_auth.rs index a807460bd9a1..570e33b094a3 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use no_example_v3::{AuthenticationApi, Claims}; @@ -84,10 +83,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -113,8 +112,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -124,4 +123,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/auth.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/auth.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs index 218967ec7a60..8ac73821c444 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use crate::models; @@ -61,8 +64,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -79,8 +82,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -92,8 +95,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -107,8 +110,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -131,8 +145,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -144,26 +158,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -187,13 +194,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -210,7 +217,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -232,7 +250,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -300,8 +329,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -363,22 +392,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn op_get( &self, @@ -409,7 +435,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -417,7 +443,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_op_get_request).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -442,9 +468,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs index ee8e118587bb..826c5e146ec7 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs index 009a31837355..6499665e9aa3 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs @@ -30,10 +30,6 @@ pub enum OpGetResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - async fn op_get( &self, op_get_request: models::OpGetRequest, @@ -46,8 +42,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; async fn op_get( @@ -72,10 +66,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs index c9632d351d20..54a7a681ca62 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -18,7 +20,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, OpGetResponse @@ -39,15 +41,17 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { api_impl: T, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -59,7 +63,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -67,21 +87,17 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()); future::ok(service) } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -118,23 +134,28 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), - ) -> Result, crate::ServiceError> where + req: (Request, C), + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -150,7 +171,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -163,7 +184,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_op_get_request) => param_op_get_request, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter OpGetRequest - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter OpGetRequest - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter OpGetRequest due to schema")), } } else { @@ -173,7 +194,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_op_get_request) => param_op_get_request, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter OpGetRequest")) + .body(body_from_str("Missing required body parameter OpGetRequest")) .expect("Unable to create Bad Request response for missing body parameter OpGetRequest")), }; @@ -182,7 +203,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_op_get_request, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -206,7 +227,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -214,14 +235,14 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, _ if path.matched(paths::ID_OP) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/.cargo/config b/samples/server/petstore/rust-server/output/openapi-v3/.cargo/config.toml similarity index 82% rename from samples/server/petstore/rust-server/output/openapi-v3/.cargo/config rename to samples/server/petstore/rust-server/output/openapi-v3/.cargo/config.toml index b8acc9c00c8c..df91f0f117f3 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/.cargo/config +++ b/samples/server/petstore/rust-server/output/openapi-v3/.cargo/config.toml @@ -6,7 +6,8 @@ rustflags = [ "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - "-W", "unsafe_code", # usage of `unsafe` code + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code "-W", "unused_qualifications", # detects unnecessarily qualified names diff --git a/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES index 5f799d4f657d..4fb75025fbc0 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -52,6 +52,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/callbacks.rs src/client/mod.rs diff --git a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml index 4f8d249eb265..5c3aee1480fd 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml @@ -12,79 +12,84 @@ default = ["client", "server"] client = [ "serde_urlencoded", "serde_ignored", "regex", "percent-encoding", "lazy_static", - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "native-tls", "hyper-openssl", "hyper-tls", "openssl", "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] cli = [ - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition # TODO: this should be updated to point at the official crate once # https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream serde-xml-rs = {git = "https://github.com/Metaswitch/serde-xml-rs" , branch = "master"} -uuid = {version = "1.3.1", features = ["serde", "v4"]} +uuid = { version = "1.17.0", features = ["serde", "v4"]} # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific -serde_urlencoded = {version = "0.6.1", optional = true} +serde_urlencoded = { version = "0.6.1", optional = true } +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs b/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs index fcfb954b6c84..4855d01b02b8 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use log::{debug, info}; // models may be unused if all inputs are primitive types #[allow(unused_imports)] @@ -37,7 +38,6 @@ use openapi_v3::{ GetRepoInfoResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -47,73 +47,73 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "My title", version = "1.0.7", about = "CLI access to My title" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, /// Bearer token if used for authentication - #[structopt(env = "OPENAPI_V3_BEARER_TOKEN", hide_env_values = true)] + #[clap(env = "OPENAPI_V3_BEARER_TOKEN", hide_env_values = true)] bearer_token: Option, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { AnyOfGet { /// list of any of objects - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] any_of: Option>, }, CallbackWithHeaderPost { url: String, }, ComplexQueryParamGet { - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] list_of_strings: Option>, }, /// Test a Form Post FormTest { - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] required_array: Option>, }, GetWithBooleanParameter { /// Let's check apostrophes get encoded properly! - #[structopt(short, long)] + #[clap(short, long)] iambool: bool, }, JsonComplexQueryParamGet { - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] list_of_strings: Option>, }, MandatoryRequestHeaderGet { @@ -133,13 +133,13 @@ enum Operation { /// Get some stuff with parameters. ParamgetGet { /// The stuff to get - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] uuid: Option, /// Some object to pass as query parameter - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] some_object: Option, /// Some list to pass as query parameter - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] some_list: Option, }, ReadonlyAuthSchemeGet { @@ -148,7 +148,7 @@ enum Operation { url: String, }, RequiredOctetStreamPut { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: swagger::ByteArray, }, ResponsesWithHeadersGet { @@ -156,40 +156,40 @@ enum Operation { Rfc7807Get { }, TwoFirstLetterHeaders { - #[structopt(long)] + #[clap(long)] x_header_one: Option, - #[structopt(long)] + #[clap(long)] x_header_two: Option, }, UntypedPropertyGet { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] object_untyped_props: Option, }, UuidGet { }, XmlExtraPost { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] duplicate_xml_object: Option, }, XmlOtherPost { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] another_xml_object: Option, }, XmlOtherPut { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] another_xml_array: Option, }, /// Post an array. It's important we test apostrophes, so include one here. XmlPost { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] xml_array: Option, }, XmlPut { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] xml_object: Option, }, EnumInPathPathParamGet { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] path_param: models::StringEnum, }, MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet { @@ -197,7 +197,7 @@ enum Operation { path_param_b: String, }, CreateRepo { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] object_param: models::ObjectParam, }, GetRepoInfo { @@ -240,7 +240,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -871,6 +871,6 @@ async fn main() -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs index 44797b0f7951..126303a5d28f 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs @@ -37,7 +37,7 @@ use openapi_v3::{Api, ApiNoContext, Claims, Client, ContextWrapperExt, models, CreateRepoResponse, GetRepoInfoResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -60,10 +60,10 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ "AnyOfGet", "CallbackWithHeaderPost", "ComplexQueryParamGet", @@ -96,17 +96,15 @@ fn main() { ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("localhost") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("8080") .help("Port to contact")) .get_matches(); @@ -135,22 +133,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -168,7 +166,7 @@ fn main() { // We could do HTTPS here, but for simplicity we don't rt.spawn(server::create("127.0.0.1:8081", false)); - match matches.value_of("operation") { + match matches.get_one::("operation") { Some("AnyOfGet") => { let result = rt.block_on(client.any_of_get( Some(&Vec::new()) diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs index fc466245a56d..20ccf81b38ae 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use openapi_v3::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use openapi_v3::CallbackApi; use openapi_v3::CallbackCallbackWithHeaderPostResponse; use openapi_v3::CallbackCallbackPostResponse; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs index 08af24903e54..14b38e400e67 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs index 1c0537f1df86..3a7a55f5d62c 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use openapi_v3::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server_auth.rs index 1c9b18394f21..51f9a4fa7721 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use openapi_v3::{AuthenticationApi, Claims}; @@ -89,10 +88,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -118,8 +117,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -129,4 +128,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/auth.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/auth.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs index 97198a90b7eb..b4655eb0975e 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -18,7 +20,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::CallbackApi as Api; use crate::CallbackCallbackWithHeaderPostResponse; @@ -52,15 +54,17 @@ mod paths { -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { api_impl: T, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -72,7 +76,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -80,11 +100,7 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()); future::ok(service) @@ -92,10 +108,10 @@ impl hyper::service::Service for MakeService where } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -132,23 +148,28 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Has> + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), - ) -> Result, crate::ServiceError> where + req: (Request, C), + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -181,7 +202,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header Information - {}", err))) + .body(body_from_string(format!("Invalid header Information - {}", err))) .expect("Unable to create Bad Request response for invalid header Information")); }, @@ -196,7 +217,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_information, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -214,7 +235,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -237,7 +258,7 @@ impl hyper::service::Service<(Request, C)> for Service where callback_request_query_url, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -255,7 +276,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -265,7 +286,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK) => method_not_allowed(), _ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK_WITH_HEADER) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs index d90cd75e2e2f..ef953a9e27ce 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use crate::models; @@ -92,8 +95,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -110,8 +113,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -123,8 +126,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -138,8 +141,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -162,8 +176,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -175,26 +189,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -218,13 +225,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -241,7 +248,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -263,7 +281,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -331,8 +360,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -394,22 +423,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Has> + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn any_of_get( &self, @@ -444,7 +470,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -461,9 +487,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -477,9 +504,10 @@ impl Api for Client where } 201 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -493,9 +521,10 @@ impl Api for Client where } 202 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -509,9 +538,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -558,7 +587,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -580,9 +609,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -631,7 +660,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -653,9 +682,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -700,7 +729,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -743,9 +772,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -792,7 +821,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -814,9 +843,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -868,7 +897,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -890,9 +919,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -937,7 +966,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -971,9 +1000,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1017,7 +1046,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1034,9 +1063,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1050,9 +1080,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1096,7 +1126,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1113,9 +1143,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1129,9 +1160,10 @@ impl Api for Client where } 201 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1147,9 +1179,10 @@ impl Api for Client where } 202 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = swagger::ByteArray(body.to_vec()); @@ -1160,9 +1193,10 @@ impl Api for Client where } 203 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1175,9 +1209,10 @@ impl Api for Client where } 204 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1191,9 +1226,10 @@ impl Api for Client where } 205 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1207,9 +1243,10 @@ impl Api for Client where } 206 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1223,9 +1260,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1269,7 +1306,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1309,9 +1346,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1355,7 +1392,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1372,9 +1409,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1388,9 +1426,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1434,7 +1472,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1456,9 +1494,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1517,7 +1555,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1534,9 +1572,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1550,9 +1589,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1596,7 +1635,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1636,9 +1675,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1685,7 +1724,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1707,9 +1746,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1754,7 +1793,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1762,7 +1801,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = param_body.0; - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/octet-stream"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1787,9 +1826,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1833,7 +1872,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1892,9 +1931,10 @@ impl Api for Client where }; let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1950,9 +1990,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1996,7 +2036,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2013,9 +2053,10 @@ impl Api for Client where match response.status().as_u16() { 204 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2029,9 +2070,10 @@ impl Api for Client where } 404 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2045,9 +2087,10 @@ impl Api for Client where } 406 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2063,9 +2106,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2111,7 +2154,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2168,9 +2211,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2215,7 +2258,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2224,7 +2267,7 @@ impl Api for Client where // Body parameter if let Some(param_object_untyped_props) = param_object_untyped_props { let body = serde_json::to_string(¶m_object_untyped_props).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/json"; @@ -2250,9 +2293,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2296,7 +2339,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2313,9 +2356,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2329,9 +2373,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2376,7 +2420,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2385,7 +2429,7 @@ impl Api for Client where // Body parameter if let Some(param_duplicate_xml_object) = param_duplicate_xml_object { let body = param_duplicate_xml_object.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/xml"; @@ -2416,9 +2460,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2463,7 +2507,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2472,7 +2516,7 @@ impl Api for Client where // Body parameter if let Some(param_another_xml_object) = param_another_xml_object { let body = param_another_xml_object.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "text/xml"; @@ -2493,9 +2537,10 @@ impl Api for Client where match response.status().as_u16() { 201 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2516,9 +2561,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2563,7 +2608,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2572,7 +2617,7 @@ impl Api for Client where // Body parameter if let Some(param_another_xml_array) = param_another_xml_array { let body = param_another_xml_array.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/xml"; @@ -2603,9 +2648,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2650,7 +2695,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2659,7 +2704,7 @@ impl Api for Client where // Body parameter if let Some(param_xml_array) = param_xml_array { let body = param_xml_array.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/xml"; @@ -2690,9 +2735,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2737,7 +2782,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2746,7 +2791,7 @@ impl Api for Client where // Body parameter if let Some(param_xml_object) = param_xml_object { let body = param_xml_object.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/xml"; @@ -2777,9 +2822,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2825,7 +2870,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2847,9 +2892,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2897,7 +2942,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2919,9 +2964,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2966,7 +3011,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2974,7 +3019,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_object_param).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -2999,9 +3044,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3047,7 +3092,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3064,9 +3109,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -3080,9 +3126,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs index 2b3485f7bbe8..1ad0e9a12ac9 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs index d6616df1fdc7..0239440e63f7 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs @@ -306,10 +306,6 @@ pub enum GetRepoInfoResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - async fn any_of_get( &self, any_of: Option<&Vec>, @@ -466,8 +462,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; async fn any_of_get( @@ -636,10 +630,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs index 5bda72e889d5..5f738acead7b 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use crate::models; @@ -42,11 +45,11 @@ use crate::CallbackCallbackPostResponse; /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone+ Has> + Send + Sync + 'static { /// Inner service client_service: S, @@ -57,11 +60,11 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone+ Has> + Send + Sync + 'static { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client") @@ -70,11 +73,11 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone+ Has> + Send + Sync + 'static { fn clone(&self) -> Self { Self { @@ -84,9 +87,9 @@ impl Clone for Client where } } -impl Client, C>, C> where +impl Client>, C>, C> where Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, - C: Clone + Send + Sync + 'static + C: Clone+ Has> + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -102,7 +105,7 @@ impl Client Self { - let client_service = hyper::client::Client::builder().build(connector); + let client_service = hyper_util::client::legacy::Client::builder().build(connector); let client_service = DropContextService::new(client_service); Self { @@ -112,8 +115,8 @@ impl Client Client, C>, C> where - C: Clone + Send + Sync + 'static +impl Client>, C>, C> where + C: Clone+ Has> + Send + Sync + 'static { /// Create an HTTP client. pub fn new_http() -> Self { @@ -128,8 +131,8 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where - C: Clone + Send + Sync + 'static +impl Client>, C>, C> where + C: Clone+ Has> + Send + Sync + 'static { /// Create a client with a TLS connection to the server. #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -192,11 +195,11 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, - C: Clone + Send + Sync + 'static + C: Clone+ Has> + Send + Sync + 'static { /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` /// @@ -214,8 +217,8 @@ impl Client where #[async_trait] impl CallbackApi for Client where S: Service< - (Request, C), - Response=Response, + (Request, C), + Response=Response>, Error=hyper::Error> + Clone + Send + Sync, S::Future: Send + 'static, S::Error: Into + fmt::Display, @@ -259,7 +262,7 @@ impl CallbackApi for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -299,9 +302,9 @@ impl CallbackApi for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -346,7 +349,7 @@ impl CallbackApi for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -368,9 +371,9 @@ impl CallbackApi for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs index 580e29ef909d..087e40a7147d 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -18,7 +20,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, AnyOfGetResponse, @@ -142,15 +144,17 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { api_impl: T, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -162,7 +166,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -170,21 +190,17 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()); future::ok(service) } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -221,23 +237,28 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Has> + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), - ) -> Result, crate::ServiceError> where + req: (Request, C), + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -265,7 +286,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_any_of.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -283,7 +304,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, AnyOfGetResponse::AlternateSuccess @@ -296,7 +317,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, AnyOfGetResponse::AnyOfSuccess @@ -309,7 +330,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -317,7 +338,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -339,7 +360,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_url) => Some(param_url), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter url - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter url - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter url")), } }, @@ -349,7 +370,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_url) => param_url, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter url")) + .body(body_from_str("Missing required query parameter url")) .expect("Unable to create Bad Request response for missing query parameter url")), }; @@ -357,7 +378,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_url, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -375,7 +396,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -399,7 +420,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_list_of_strings.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -417,7 +438,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -429,7 +450,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { // Form parameters @@ -441,7 +462,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_required_array.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -459,7 +480,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -467,7 +488,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -487,7 +508,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_iambool) => Some(param_iambool), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter iambool - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter iambool - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter iambool")), } }, @@ -497,7 +518,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_iambool) => param_iambool, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter iambool")) + .body(body_from_str("Missing required query parameter iambool")) .expect("Unable to create Bad Request response for missing query parameter iambool")), }; @@ -505,7 +526,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_iambool, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -523,7 +544,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -545,7 +566,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_list_of_strings) => Some(param_list_of_strings), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter list-of-strings - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter list-of-strings - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter list-of-strings")), } }, @@ -556,7 +577,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_list_of_strings.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -574,7 +595,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -593,7 +614,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header X-Header - {}", err))) + .body(body_from_string(format!("Invalid header X-Header - {}", err))) .expect("Unable to create Bad Request response for invalid header X-Header")); }, @@ -601,7 +622,7 @@ impl hyper::service::Service<(Request, C)> for Service where None => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required header X-Header")) + .body(body_from_str("Missing required header X-Header")) .expect("Unable to create Bad Request response for missing required header X-Header")); } }; @@ -610,7 +631,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_x_header, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -628,7 +649,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -640,7 +661,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.merge_patch_json_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -658,7 +679,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/merge-patch+json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -666,7 +687,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -678,7 +699,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.multiget_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -696,7 +717,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, MultigetGetResponse::XMLRsp @@ -709,7 +730,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, MultigetGetResponse::OctetRsp @@ -722,7 +743,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/octet-stream")); // Binary Body let body = body.0; - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, MultigetGetResponse::StringRsp @@ -735,7 +756,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for text/plain")); // Plain text Body let body = body; - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, MultigetGetResponse::DuplicateResponseLongText @@ -748,7 +769,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, MultigetGetResponse::DuplicateResponseLongText_2 @@ -761,7 +782,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, MultigetGetResponse::DuplicateResponseLongText_3 @@ -774,7 +795,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -782,7 +803,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -796,7 +817,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -811,7 +832,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -824,7 +845,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.multiple_auth_scheme_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -842,7 +863,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -854,7 +875,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.one_of_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -872,7 +893,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -880,7 +901,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -892,7 +913,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.override_server_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -910,7 +931,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -932,7 +953,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_uuid) => Some(param_uuid), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter uuid - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter uuid - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter uuid")), } }, @@ -949,7 +970,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_some_object) => Some(param_some_object), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter someObject - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter someObject - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter someObject")), } }, @@ -966,7 +987,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_some_list) => Some(param_some_list), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter someList - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter someList - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter someList")), } }, @@ -979,7 +1000,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_some_list, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -997,7 +1018,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -1005,7 +1026,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1019,7 +1040,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -1033,7 +1054,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -1046,7 +1067,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.readonly_auth_scheme_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1064,7 +1085,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1086,7 +1107,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_url) => Some(param_url), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter url - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter url - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter url")), } }, @@ -1096,7 +1117,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_url) => param_url, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter url")) + .body(body_from_str("Missing required query parameter url")) .expect("Unable to create Bad Request response for missing query parameter url")), }; @@ -1104,7 +1125,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_url, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1122,7 +1143,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1134,7 +1155,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let param_body: Option = if !body.is_empty() { @@ -1146,7 +1167,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -1155,7 +1176,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1173,7 +1194,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1181,7 +1202,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1191,7 +1212,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.responses_with_headers_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1214,7 +1235,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling success_info header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling success_info header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -1230,7 +1251,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling bool_header header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling bool_header header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -1247,7 +1268,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling object_header header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling object_header header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -1263,7 +1284,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, ResponsesWithHeadersGetResponse::PreconditionFailed @@ -1280,7 +1301,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling further_info header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling further_info header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -1297,7 +1318,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling failure_info header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling failure_info header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -1314,7 +1335,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1326,7 +1347,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.rfc7807_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1344,7 +1365,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, Rfc7807GetResponse::NotFound @@ -1357,7 +1378,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/problem+json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, Rfc7807GetResponse::NotAcceptable @@ -1370,7 +1391,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/problem+xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -1378,7 +1399,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1397,7 +1418,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header x-header-one - {}", err))) + .body(body_from_string(format!("Invalid header x-header-one - {}", err))) .expect("Unable to create Bad Request response for invalid header x-header-one")); }, @@ -1415,7 +1436,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header x-header-two - {}", err))) + .body(body_from_string(format!("Invalid header x-header-two - {}", err))) .expect("Unable to create Bad Request response for invalid header x-header-two")); }, @@ -1430,7 +1451,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_x_header_two, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1448,7 +1469,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1460,7 +1481,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1482,7 +1503,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_object_untyped_props, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1506,7 +1527,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1514,7 +1535,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1524,7 +1545,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.uuid_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1542,7 +1563,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -1550,7 +1571,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1562,7 +1583,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1584,7 +1605,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_duplicate_xml_object, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1613,7 +1634,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1621,7 +1642,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1631,7 +1652,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1653,7 +1674,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_another_xml_object, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1681,7 +1702,7 @@ impl hyper::service::Service<(Request, C)> for Service where // An empty string is used to indicate a global namespace in xmltree. namespaces.insert("".to_string(), models::AnotherXmlObject::NAMESPACE.to_string()); let body = serde_xml_rs::to_string_with_namespaces(&body, namespaces).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, XmlOtherPostResponse::BadRequest @@ -1694,7 +1715,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1702,7 +1723,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1712,7 +1733,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1734,7 +1755,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_another_xml_array, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1763,7 +1784,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1771,7 +1792,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1781,7 +1802,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1803,7 +1824,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_xml_array, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1832,7 +1853,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1840,7 +1861,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1850,7 +1871,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1872,7 +1893,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_xml_object, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1901,7 +1922,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1909,7 +1930,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1930,12 +1951,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_path_param) => param_path_param, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter path_param: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter path_param: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -1943,7 +1964,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_path_param, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1961,7 +1982,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1984,12 +2005,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_path_param_a) => param_path_param_a, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter path_param_a: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter path_param_a: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param_a"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param_a"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -1998,12 +2019,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_path_param_b) => param_path_param_b, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter path_param_b: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter path_param_b: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param_b"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param_b"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -2012,7 +2033,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_path_param_b, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2030,7 +2051,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2042,7 +2063,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -2055,7 +2076,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_object_param) => param_object_param, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter ObjectParam - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter ObjectParam - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter ObjectParam due to schema")), } } else { @@ -2065,7 +2086,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_object_param) => param_object_param, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter ObjectParam")) + .body(body_from_str("Missing required body parameter ObjectParam")) .expect("Unable to create Bad Request response for missing body parameter ObjectParam")), }; @@ -2074,7 +2095,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_object_param, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2098,7 +2119,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2106,7 +2127,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2127,12 +2148,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_repo_id) => param_repo_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter repoId: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter repoId: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["repoId"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["repoId"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -2140,7 +2161,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_repo_id, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2158,7 +2179,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -2166,7 +2187,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2202,7 +2223,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_XML_EXTRA) => method_not_allowed(), _ if path.matched(paths::ID_XML_OTHER) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/.cargo/config b/samples/server/petstore/rust-server/output/ops-v3/.cargo/config.toml similarity index 82% rename from samples/server/petstore/rust-server/output/ops-v3/.cargo/config rename to samples/server/petstore/rust-server/output/ops-v3/.cargo/config.toml index b8acc9c00c8c..df91f0f117f3 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/.cargo/config +++ b/samples/server/petstore/rust-server/output/ops-v3/.cargo/config.toml @@ -6,7 +6,8 @@ rustflags = [ "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - "-W", "unsafe_code", # usage of `unsafe` code + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code "-W", "unused_qualifications", # detects unnecessarily qualified names diff --git a/samples/server/petstore/rust-server/output/ops-v3/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/ops-v3/.openapi-generator/FILES index ce2109b1de2e..a4a30ca84661 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/ops-v3/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -13,6 +13,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/mod.rs src/context.rs diff --git a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml index 0c33be7b5ea2..0de2eee59d68 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml @@ -10,73 +10,78 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] cli = [ - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/ops-v3/bin/cli.rs b/samples/server/petstore/rust-server/output/ops-v3/bin/cli.rs index 39f3ad4646cd..19bb5c380b8a 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use log::{debug, info}; // models may be unused if all inputs are primitive types #[allow(unused_imports)] @@ -44,7 +45,6 @@ use ops_v3::{ Op9GetResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -54,44 +54,44 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "Regression test for large number of operations", version = "0.0.1", about = "CLI access to Regression test for large number of operations" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { Op10Get { }, @@ -204,7 +204,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -754,6 +754,6 @@ async fn main() -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs index 9d9bfc6d9589..3d7f32c7aac7 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs @@ -43,7 +43,7 @@ use ops_v3::{Api, ApiNoContext, Claims, Client, ContextWrapperExt, models, Op8GetResponse, Op9GetResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -66,10 +66,10 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ "Op10Get", "Op11Get", "Op12Get", @@ -110,17 +110,15 @@ fn main() { ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("localhost") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("8080") .help("Port to contact")) .get_matches(); @@ -144,22 +142,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -174,7 +172,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); - match matches.value_of("operation") { + match matches.get_one::("operation") { Some("Op10Get") => { let result = rt.block_on(client.op10_get( )); diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs index 227fe7e73155..8357b32e2610 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs index d51ecdd70289..220205dbad01 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use ops_v3::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + ops_v3::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - ops_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server_auth.rs index 19eb6c6add4a..7b2357c64404 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use ops_v3::{AuthenticationApi, Claims}; @@ -84,10 +83,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -113,8 +112,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -124,4 +123,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/auth.rs b/samples/server/petstore/rust-server/output/ops-v3/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/auth.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs index f3dbc73c9892..94702916598d 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use crate::models; @@ -97,8 +100,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -115,8 +118,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -128,8 +131,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -143,8 +146,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -167,8 +181,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -180,26 +194,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -223,13 +230,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -246,7 +253,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -268,7 +286,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -336,8 +365,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -399,22 +428,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn op10_get( &self, @@ -444,7 +470,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -466,9 +492,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -512,7 +538,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -534,9 +560,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -580,7 +606,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -602,9 +628,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -648,7 +674,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -670,9 +696,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -716,7 +742,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -738,9 +764,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -784,7 +810,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -806,9 +832,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -852,7 +878,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -874,9 +900,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -920,7 +946,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -942,9 +968,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -988,7 +1014,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1010,9 +1036,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1056,7 +1082,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1078,9 +1104,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1124,7 +1150,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1146,9 +1172,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1192,7 +1218,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1214,9 +1240,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1260,7 +1286,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1282,9 +1308,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1328,7 +1354,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1350,9 +1376,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1396,7 +1422,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1418,9 +1444,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1464,7 +1490,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1486,9 +1512,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1532,7 +1558,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1554,9 +1580,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1600,7 +1626,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1622,9 +1648,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1668,7 +1694,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1690,9 +1716,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1736,7 +1762,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1758,9 +1784,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1804,7 +1830,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1826,9 +1852,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1872,7 +1898,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1894,9 +1920,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1940,7 +1966,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1962,9 +1988,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2008,7 +2034,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2030,9 +2056,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2076,7 +2102,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2098,9 +2124,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2144,7 +2170,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2166,9 +2192,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2212,7 +2238,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2234,9 +2260,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2280,7 +2306,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2302,9 +2328,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2348,7 +2374,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2370,9 +2396,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2416,7 +2442,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2438,9 +2464,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2484,7 +2510,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2506,9 +2532,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2552,7 +2578,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2574,9 +2600,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2620,7 +2646,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2642,9 +2668,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2688,7 +2714,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2710,9 +2736,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2756,7 +2782,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2778,9 +2804,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2824,7 +2850,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2846,9 +2872,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2892,7 +2918,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2914,9 +2940,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/context.rs b/samples/server/petstore/rust-server/output/ops-v3/src/context.rs index ee8e118587bb..826c5e146ec7 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs index 866ce4e4654a..d41c95464cb2 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs @@ -246,10 +246,6 @@ pub enum Op9GetResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - async fn op10_get( &self, context: &C) -> Result; @@ -405,8 +401,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; async fn op10_get( @@ -574,10 +568,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs index 47846655bfb7..055e9ef4a087 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -18,7 +20,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, Op10GetResponse, @@ -147,15 +149,17 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { api_impl: T, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -167,7 +171,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -175,21 +195,17 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()); future::ok(service) } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -226,23 +242,28 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), - ) -> Result, crate::ServiceError> where + req: (Request, C), + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -258,7 +279,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op10_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -276,7 +297,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -288,7 +309,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op11_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -306,7 +327,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -318,7 +339,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op12_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -336,7 +357,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -348,7 +369,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op13_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -366,7 +387,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -378,7 +399,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op14_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -396,7 +417,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -408,7 +429,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op15_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -426,7 +447,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -438,7 +459,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op16_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -456,7 +477,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -468,7 +489,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op17_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -486,7 +507,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -498,7 +519,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op18_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -516,7 +537,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -528,7 +549,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op19_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -546,7 +567,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -558,7 +579,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op1_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -576,7 +597,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -588,7 +609,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op20_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -606,7 +627,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -618,7 +639,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op21_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -636,7 +657,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -648,7 +669,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op22_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -666,7 +687,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -678,7 +699,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op23_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -696,7 +717,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -708,7 +729,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op24_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -726,7 +747,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -738,7 +759,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op25_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -756,7 +777,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -768,7 +789,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op26_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -786,7 +807,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -798,7 +819,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op27_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -816,7 +837,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -828,7 +849,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op28_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -846,7 +867,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -858,7 +879,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op29_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -876,7 +897,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -888,7 +909,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op2_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -906,7 +927,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -918,7 +939,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op30_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -936,7 +957,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -948,7 +969,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op31_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -966,7 +987,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -978,7 +999,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op32_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -996,7 +1017,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1008,7 +1029,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op33_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1026,7 +1047,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1038,7 +1059,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op34_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1056,7 +1077,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1068,7 +1089,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op35_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1086,7 +1107,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1098,7 +1119,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op36_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1116,7 +1137,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1128,7 +1149,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op37_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1146,7 +1167,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1158,7 +1179,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op3_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1176,7 +1197,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1188,7 +1209,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op4_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1206,7 +1227,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1218,7 +1239,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op5_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1236,7 +1257,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1248,7 +1269,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op6_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1266,7 +1287,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1278,7 +1299,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op7_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1296,7 +1317,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1308,7 +1329,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op8_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1326,7 +1347,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1338,7 +1359,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.op9_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1356,7 +1377,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1401,7 +1422,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_OP8) => method_not_allowed(), _ if path.matched(paths::ID_OP9) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/ops-v3/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config deleted file mode 100644 index b8acc9c00c8c..000000000000 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config +++ /dev/null @@ -1,18 +0,0 @@ -[build] -rustflags = [ - "-W", "missing_docs", # detects missing documentation for public members - - "-W", "trivial_casts", # detects trivial casts which could be removed - - "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - - "-W", "unsafe_code", # usage of `unsafe` code - - "-W", "unused_qualifications", # detects unnecessarily qualified names - - "-W", "unused_extern_crates", # extern crates that are never used - - "-W", "unused_import_braces", # unnecessary braces around an imported item - - "-D", "warnings", # all warnings should be denied -] diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config.toml b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config.toml new file mode 100644 index 000000000000..df91f0f117f3 --- /dev/null +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.cargo/config.toml @@ -0,0 +1,19 @@ +[build] +rustflags = [ + "-W", "missing_docs", # detects missing documentation for public members + + "-W", "trivial_casts", # detects trivial casts which could be removed + + "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed + + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code + + "-W", "unused_qualifications", # detects unnecessarily qualified names + + "-W", "unused_extern_crates", # extern crates that are never used + + "-W", "unused_import_braces", # unnecessary braces around an imported item + + "-D", "warnings", # all warnings should be denied +] diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES index e515b3eb7511..2efe1ec57cfe 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -70,6 +70,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/mod.rs src/context.rs diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml index 0c809c91fdd6..557027d46e58 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml @@ -13,7 +13,7 @@ client = [ "mime_0_2", "multipart", "multipart/client", "swagger/multipart_form", "serde_urlencoded", - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "mime_0_2", @@ -22,30 +22,30 @@ server = [ ] cli = [ "dialoguer", - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition # TODO: this should be updated to point at the official crate once @@ -53,44 +53,49 @@ validator = { version = "0.16", features = ["derive"] } serde-xml-rs = {git = "https://github.com/Metaswitch/serde-xml-rs" , branch = "master"} mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } -uuid = {version = "1.3.1", features = ["serde", "v4"]} +uuid = { version = "1.17.0", features = ["serde", "v4"]} # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific -serde_urlencoded = {version = "0.6.1", optional = true} +serde_urlencoded = { version = "0.6.1", optional = true } +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } dialoguer = { version = "0.8", optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/bin/cli.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/bin/cli.rs index 9141802f5891..9d02c3e2d1be 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use dialoguer::Confirm; use log::{debug, info}; // models may be unused if all inputs are primitive types @@ -43,7 +44,6 @@ use petstore_with_fake_endpoints_models_for_testing::{ UpdateUserResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -53,93 +53,93 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "OpenAPI Petstore", version = "1.0.0", about = "CLI access to OpenAPI Petstore" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, /// Don't ask for any confirmation prompts #[allow(dead_code)] - #[structopt(short, long)] + #[clap(short, long)] force: bool, /// Bearer token if used for authentication - #[structopt(env = "PETSTORE_WITH_FAKE_ENDPOINTS_MODELS_FOR_TESTING_BEARER_TOKEN", hide_env_values = true)] + #[clap(env = "PETSTORE_WITH_FAKE_ENDPOINTS_MODELS_FOR_TESTING_BEARER_TOKEN", hide_env_values = true)] bearer_token: Option, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { /// To test special tags TestSpecialTags { /// client model - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::Client, }, Call123example { }, FakeOuterBooleanSerialize { /// Input boolean as post body - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: Option, }, FakeOuterCompositeSerialize { /// Input composite as post body - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: Option, }, FakeOuterNumberSerialize { /// Input number as post body - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: Option, }, FakeOuterStringSerialize { /// Input string as post body - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: Option, }, FakeResponseWithNumericalDescription { }, TestBodyWithQueryParams { query: String, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::User, }, /// To test \"client\" model TestClientModel { /// client model - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::Client, }, /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 @@ -151,7 +151,7 @@ enum Operation { /// None pattern_without_delimiter: String, /// None - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] byte: swagger::ByteArray, /// None integer: Option, @@ -164,7 +164,7 @@ enum Operation { /// None string: Option, /// None - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] binary: Option, /// None date: Option, @@ -178,30 +178,30 @@ enum Operation { /// To test enum parameters TestEnumParameters { /// Header parameter enum test (string array) - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] enum_header_string_array: Option>, /// Header parameter enum test (string) - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] enum_header_string: Option, /// Query parameter enum test (string array) - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] enum_query_string_array: Option>, /// Query parameter enum test (string) - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] enum_query_string: Option, /// Query parameter enum test (double) - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] enum_query_integer: Option, /// Query parameter enum test (double) - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] enum_query_double: Option, - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] enum_form_string: Option, }, /// test inline additionalProperties TestInlineAdditionalProperties { /// request body - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::>)] param: std::collections::HashMap, }, /// test json serialization of form data @@ -218,31 +218,31 @@ enum Operation { /// To test class name in snake case TestClassname { /// client model - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::Client, }, /// Add a new pet to the store AddPet { /// Pet object that needs to be added to the store - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::Pet, }, /// Finds Pets by status FindPetsByStatus { /// Status values that need to be considered for filter - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] status: Vec, }, /// Finds Pets by tags FindPetsByTags { /// Tags to filter by - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] tags: Vec, }, /// Update an existing pet UpdatePet { /// Pet object that needs to be added to the store - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::Pet, }, /// Deletes a pet @@ -272,7 +272,7 @@ enum Operation { /// Additional data to pass to server additional_metadata: Option, /// file to upload - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] file: Option, }, /// Returns pet inventories by status @@ -281,7 +281,7 @@ enum Operation { /// Place an order for a pet PlaceOrder { /// order placed for purchasing the pet - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::Order, }, /// Delete purchase order by ID @@ -297,19 +297,19 @@ enum Operation { /// Create user CreateUser { /// Created user object - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::User, }, /// Creates list of users with given input array CreateUsersWithArrayInput { /// List of user object - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] body: Vec, }, /// Creates list of users with given input array CreateUsersWithListInput { /// List of user object - #[structopt(parse(try_from_str = parse_json), long)] + #[clap(value_parser = parse_json::>), long] body: Vec, }, /// Logs user into the system @@ -337,7 +337,7 @@ enum Operation { /// name that need to be deleted username: String, /// Updated user object - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] body: models::User, }, } @@ -377,7 +377,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -1148,6 +1148,6 @@ fn prompt(force: bool, text: &str) -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs index 62b1a8c1389b..56890a328147 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs @@ -41,7 +41,7 @@ use petstore_with_fake_endpoints_models_for_testing::{Api, ApiNoContext, Claims, GetUserByNameResponse, UpdateUserResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -64,10 +64,10 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ "Call123example", "FakeOuterBooleanSerialize", "FakeOuterCompositeSerialize", @@ -96,17 +96,15 @@ fn main() { ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("petstore.swagger.io") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("80") .help("Port to contact")) .get_matches(); @@ -133,22 +131,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -163,7 +161,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); - match matches.value_of("operation") { + match matches.get_one::("operation") { /* Disabled because there's no example. Some("TestSpecialTags") => { let result = rt.block_on(client.test_special_tags( diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs index 63e175c3dc90..766a6e475ae2 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); - let addr = "127.0.0.1:80"; + let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs index 2920da486195..1fee290102eb 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use petstore_with_fake_endpoints_models_for_testing::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + petstore_with_fake_endpoints_models_for_testing::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - petstore_with_fake_endpoints_models_for_testing::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server_auth.rs index 1593a36e2c41..514a4af9cab9 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use petstore_with_fake_endpoints_models_for_testing::{AuthenticationApi, Claims}; @@ -87,10 +86,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -116,8 +115,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -127,4 +126,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/auth.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/auth.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs index 8c35448de11c..f35b8632548d 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use mime::Mime; use std::io::Cursor; @@ -98,8 +101,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -116,8 +119,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -129,8 +132,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -144,8 +147,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -168,8 +182,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -181,26 +195,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -224,13 +231,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -247,7 +254,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -269,7 +287,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -337,8 +366,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -400,22 +429,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Has> + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn test_special_tags( &self, @@ -446,7 +472,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PATCH") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -454,7 +480,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -474,9 +500,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -490,9 +517,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -536,7 +563,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -558,9 +585,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -605,7 +632,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -614,7 +641,7 @@ impl Api for Client where // Body parameter if let Some(param_body) = param_body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/json"; @@ -635,9 +662,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -651,9 +679,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -698,7 +726,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -707,7 +735,7 @@ impl Api for Client where // Body parameter if let Some(param_body) = param_body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/json"; @@ -728,9 +756,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -744,9 +773,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -791,7 +820,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -800,7 +829,7 @@ impl Api for Client where // Body parameter if let Some(param_body) = param_body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/json"; @@ -821,9 +850,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -837,9 +867,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -884,7 +914,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -893,7 +923,7 @@ impl Api for Client where // Body parameter if let Some(param_body) = param_body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); } let header = "application/json"; @@ -914,9 +944,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -930,9 +961,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -976,7 +1007,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -998,9 +1029,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1048,7 +1079,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1056,7 +1087,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1081,9 +1112,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1128,7 +1159,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PATCH") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1136,7 +1167,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1156,9 +1187,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1172,9 +1204,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1232,7 +1264,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1352,9 +1384,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1421,7 +1453,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1501,9 +1533,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1548,7 +1580,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1556,7 +1588,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_param).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1581,9 +1613,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1629,7 +1661,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1670,9 +1702,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1718,7 +1750,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1740,9 +1772,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1790,7 +1822,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PATCH") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1798,7 +1830,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1826,9 +1858,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1842,9 +1875,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1889,7 +1922,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1897,7 +1930,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = param_body.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1940,9 +1973,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1989,7 +2022,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2024,9 +2057,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2047,9 +2081,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2096,7 +2130,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2131,9 +2165,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2154,9 +2189,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2201,7 +2236,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2209,7 +2244,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = param_body.as_xml(); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -2262,9 +2297,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2311,7 +2346,7 @@ impl Api for Client where let mut request = match Request::builder() .method("DELETE") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2369,9 +2404,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2417,7 +2452,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2442,9 +2477,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2470,9 +2506,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2520,7 +2556,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2583,9 +2619,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2633,7 +2669,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2687,7 +2723,7 @@ impl Api for Client where (body_string, multipart_header) }; - *request.body_mut() = Body::from(body_string); + *request.body_mut() = body_from_string(body_string); request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) { Ok(h) => h, @@ -2725,9 +2761,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2741,9 +2778,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2787,7 +2824,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2812,9 +2849,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2828,9 +2866,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2875,7 +2913,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -2883,7 +2921,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -2903,9 +2941,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -2926,9 +2965,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -2974,7 +3013,7 @@ impl Api for Client where let mut request = match Request::builder() .method("DELETE") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3001,9 +3040,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3049,7 +3088,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3066,9 +3105,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -3094,9 +3134,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3141,7 +3181,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3149,7 +3189,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -3174,9 +3214,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3221,7 +3261,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3229,7 +3269,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -3254,9 +3294,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3301,7 +3341,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3309,7 +3349,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -3334,9 +3374,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3386,7 +3426,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3431,9 +3471,10 @@ impl Api for Client where }; let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -3458,9 +3499,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3504,7 +3545,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3526,9 +3567,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3574,7 +3615,7 @@ impl Api for Client where let mut request = match Request::builder() .method("DELETE") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3601,9 +3642,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3649,7 +3690,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3666,9 +3707,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -3694,9 +3736,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -3743,7 +3785,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -3751,7 +3793,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -3781,9 +3823,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs index d821895b62ad..8e34a0d708fe 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs index b910c9ae6b23..e483f7e1075c 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs @@ -325,10 +325,6 @@ pub enum UpdateUserResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - /// To test special tags async fn test_special_tags( &self, @@ -562,8 +558,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; /// To test special tags @@ -809,10 +803,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs index 0b0af66381ed..7ef297f67192 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -20,7 +22,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, TestSpecialTagsResponse, @@ -157,16 +159,18 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { api_impl: T, multipart_form_size_limit: Option, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -189,7 +193,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -197,11 +217,7 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()) .multipart_form_size_limit(self.multipart_form_size_limit); @@ -209,10 +225,10 @@ impl hyper::service::Service for MakeService where } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -262,24 +278,29 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Has> + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), + req: (Request, C), multipart_form_size_limit: Option, - ) -> Result, crate::ServiceError> where + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -295,7 +316,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -308,7 +329,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -318,7 +339,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -327,7 +348,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -351,7 +372,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -359,7 +380,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -367,7 +388,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -377,7 +398,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.call123example( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -395,7 +416,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -407,7 +428,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -429,7 +450,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -453,7 +474,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for */*")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -461,7 +482,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -469,7 +490,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -479,7 +500,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -501,7 +522,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -525,7 +546,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for */*")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -533,7 +554,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -541,7 +562,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -551,7 +572,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -573,7 +594,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -597,7 +618,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for */*")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -605,7 +626,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -613,7 +634,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -623,7 +644,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -645,7 +666,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -669,7 +690,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for */*")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -677,7 +698,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -685,7 +706,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -695,7 +716,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.fake_response_with_numerical_description( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -713,7 +734,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -735,7 +756,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_query) => Some(param_query), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter query - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter query - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter query")), } }, @@ -745,14 +766,14 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_query) => param_query, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter query")) + .body(body_from_str("Missing required query parameter query")) .expect("Unable to create Bad Request response for missing query parameter query")), }; // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -765,7 +786,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -775,7 +796,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -785,7 +806,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -809,7 +830,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -817,7 +838,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -827,7 +848,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -840,7 +861,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -850,7 +871,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -859,7 +880,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -883,7 +904,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -891,7 +912,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -899,7 +920,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -911,7 +932,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; } @@ -919,7 +940,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { // Form parameters @@ -970,7 +991,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_callback, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -993,7 +1014,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1001,7 +1022,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1018,7 +1039,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header enum_header_string_array - {}", err))) + .body(body_from_string(format!("Invalid header enum_header_string_array - {}", err))) .expect("Unable to create Bad Request response for invalid header enum_header_string_array")); }, @@ -1036,7 +1057,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header enum_header_string - {}", err))) + .body(body_from_string(format!("Invalid header enum_header_string - {}", err))) .expect("Unable to create Bad Request response for invalid header enum_header_string")); }, @@ -1067,7 +1088,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_enum_query_string) => Some(param_enum_query_string), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter enum_query_string - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter enum_query_string - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter enum_query_string")), } }, @@ -1084,7 +1105,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_enum_query_integer) => Some(param_enum_query_integer), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter enum_query_integer - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter enum_query_integer - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter enum_query_integer")), } }, @@ -1101,7 +1122,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_enum_query_double) => Some(param_enum_query_double), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter enum_query_double - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter enum_query_double - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter enum_query_double")), } }, @@ -1111,7 +1132,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { // Form parameters @@ -1129,7 +1150,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_enum_form_string, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1152,7 +1173,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1160,7 +1181,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1170,7 +1191,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1183,7 +1204,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_param) => param_param, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter param - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter param - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter param due to schema")), } } else { @@ -1193,7 +1214,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_param) => param_param, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter param")) + .body(body_from_str("Missing required body parameter param")) .expect("Unable to create Bad Request response for missing body parameter param")), }; @@ -1202,7 +1223,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_param, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1226,7 +1247,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1234,7 +1255,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1244,7 +1265,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { // Form parameters @@ -1259,7 +1280,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_param2, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1277,7 +1298,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1285,7 +1306,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1306,12 +1327,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_hyphen_param) => param_hyphen_param, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter hyphen-param: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter hyphen-param: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["hyphen-param"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["hyphen-param"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -1319,7 +1340,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_hyphen_param, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1337,7 +1358,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1351,7 +1372,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; } @@ -1359,7 +1380,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1372,7 +1393,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -1382,7 +1403,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -1391,7 +1412,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1415,7 +1436,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -1423,7 +1444,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1431,7 +1452,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1443,7 +1464,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -1458,7 +1479,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -1471,7 +1492,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1484,7 +1505,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -1494,7 +1515,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -1503,7 +1524,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1527,7 +1548,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1535,7 +1556,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1547,7 +1568,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -1562,7 +1583,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -1582,7 +1603,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_status.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1600,7 +1621,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, FindPetsByStatusResponse::InvalidStatusValue @@ -1613,7 +1634,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1627,7 +1648,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -1642,7 +1663,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -1662,7 +1683,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_tags.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1680,7 +1701,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, FindPetsByTagsResponse::InvalidTagValue @@ -1693,7 +1714,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1707,7 +1728,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -1722,7 +1743,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -1735,7 +1756,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -1748,7 +1769,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -1758,7 +1779,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -1767,7 +1788,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1801,7 +1822,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1809,7 +1830,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -1821,7 +1842,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -1836,7 +1857,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -1860,12 +1881,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_pet_id) => param_pet_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter petId: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -1879,7 +1900,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(err) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Invalid header api_key - {}", err))) + .body(body_from_string(format!("Invalid header api_key - {}", err))) .expect("Unable to create Bad Request response for invalid header api_key")); }, @@ -1894,7 +1915,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_api_key, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1912,7 +1933,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -1926,7 +1947,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; } @@ -1945,12 +1966,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_pet_id) => param_pet_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter petId: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -1958,7 +1979,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_pet_id, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -1976,7 +1997,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, GetPetByIdResponse::InvalidIDSupplied @@ -1994,7 +2015,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2008,7 +2029,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -2023,7 +2044,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -2047,19 +2068,19 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_pet_id) => param_pet_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter petId: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { // Form parameters @@ -2075,7 +2096,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_status, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2093,7 +2114,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2101,7 +2122,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2113,7 +2134,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; @@ -2128,7 +2149,7 @@ impl hyper::service::Service<(Request, C)> for Service where let missing_scopes = required_scopes.difference(scopes); return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from(missing_scopes.fold( + .body(body_from_string(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) @@ -2152,26 +2173,26 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_pet_id) => param_pet_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter petId: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let boundary = match swagger::multipart::form::boundary(&headers) { Some(boundary) => boundary.to_string(), None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Couldn't find valid multipart body".to_string())) + .body(body_from_str("Couldn't find valid multipart body".to_string())) .expect("Unable to create Bad Request response for incorrect boundary")), }; @@ -2189,31 +2210,31 @@ impl hyper::service::Service<(Request, C)> for Service where SaveResult::Partial(_, PartialReason::CountLimit) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to excessive parts".to_string())) + .body(body_from_str("Unable to process message part due to excessive parts".to_string())) .expect("Unable to create Bad Request response due to excessive parts")) }, SaveResult::Partial(_, PartialReason::SizeLimit) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to excessive data".to_string())) + .body(body_from_str("Unable to process message part due to excessive data".to_string())) .expect("Unable to create Bad Request response due to excessive data")) }, SaveResult::Partial(_, PartialReason::Utf8Error(_)) => { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Unable to process message part due to invalid data".to_string())) + .body(body_from_str("Unable to process message part due to invalid data".to_string())) .expect("Unable to create Bad Request response due to invalid data")) }, SaveResult::Partial(_, PartialReason::IoError(_)) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from("Failed to process message part due an internal error".to_string())) + .body(body_from_str("Failed to process message part due an internal error".to_string())) .expect("Unable to create Internal Server Error response due to an internal error")) }, SaveResult::Error(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from("Failed to process all message parts due to an internal error".to_string())) + .body(body_from_str("Failed to process all message parts due to an internal error".to_string())) .expect("Unable to create Internal Server Error response due to an internal error")) }, }; @@ -2230,7 +2251,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("additional_metadata data does not match API definition : {}", e))) + .body(body_from_string(format!("additional_metadata data does not match API definition : {}", e))) .expect("Unable to create Bad Request due to missing required form parameter additional_metadata")) } }; @@ -2254,7 +2275,7 @@ impl hyper::service::Service<(Request, C)> for Service where return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("file data does not match API definition : {}", e))) + .body(body_from_string(format!("file data does not match API definition : {}", e))) .expect("Unable to create Bad Request due to missing required form parameter file")) } }; @@ -2273,7 +2294,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_file, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2291,7 +2312,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -2299,7 +2320,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2307,7 +2328,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2319,7 +2340,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; } @@ -2327,7 +2348,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.get_inventory( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2345,7 +2366,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -2353,7 +2374,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2365,7 +2386,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -2378,7 +2399,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -2388,7 +2409,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -2397,7 +2418,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2421,7 +2442,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, PlaceOrderResponse::InvalidOrder @@ -2434,7 +2455,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2442,7 +2463,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2463,12 +2484,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_order_id) => param_order_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter order_id: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter order_id: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -2476,7 +2497,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_order_id, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2499,7 +2520,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2522,12 +2543,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_order_id) => param_order_id, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter order_id: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter order_id: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -2535,7 +2556,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_order_id, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2553,7 +2574,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, GetOrderByIdResponse::InvalidIDSupplied @@ -2571,7 +2592,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2583,7 +2604,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -2596,7 +2617,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -2606,7 +2627,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -2615,7 +2636,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2639,7 +2660,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2647,7 +2668,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2657,7 +2678,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -2670,7 +2691,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -2680,7 +2701,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -2689,7 +2710,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2713,7 +2734,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2721,7 +2742,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2731,7 +2752,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -2744,7 +2765,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -2754,7 +2775,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -2763,7 +2784,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body.as_ref(), &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2787,7 +2808,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2795,7 +2816,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -2815,7 +2836,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_username) => Some(param_username), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter username - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter username - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter username")), } }, @@ -2825,7 +2846,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_username) => param_username, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter username")) + .body(body_from_str("Missing required query parameter username")) .expect("Unable to create Bad Request response for missing query parameter username")), }; let param_password = query_params.iter().filter(|e| e.0 == "password").map(|e| e.1.clone()) @@ -2839,7 +2860,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_password) => Some(param_password), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse query parameter password - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse query parameter password - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid query parameter password")), } }, @@ -2849,7 +2870,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_password) => param_password, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required query parameter password")) + .body(body_from_str("Missing required query parameter password")) .expect("Unable to create Bad Request response for missing query parameter password")), }; @@ -2858,7 +2879,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_password, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2881,7 +2902,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling x_rate_limit header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling x_rate_limit header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -2898,7 +2919,7 @@ impl hyper::service::Service<(Request, C)> for Service where Err(e) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("An internal server error occurred handling x_expires_after header - {}", e))) + .body(body_from_string(format!("An internal server error occurred handling x_expires_after header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) } }; @@ -2914,7 +2935,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, LoginUserResponse::InvalidUsername @@ -2927,7 +2948,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2939,7 +2960,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.logout_user( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -2957,7 +2978,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -2980,12 +3001,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_username) => param_username, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter username: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter username: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -2993,7 +3014,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_username, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -3016,7 +3037,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -3039,12 +3060,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_username) => param_username, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter username: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter username: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; @@ -3052,7 +3073,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_username, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -3070,7 +3091,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/xml")); // XML Body let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, GetUserByNameResponse::InvalidUsernameSupplied @@ -3088,7 +3109,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -3111,19 +3132,19 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_username) => param_username, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse path parameter username: {}", e))) + .body(body_from_string(format!("Couldn't parse path parameter username: {}", e))) .expect("Unable to create Bad Request response for invalid path parameter")), }, Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) + .body(body_from_string(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) .expect("Unable to create Bad Request response for invalid percent decode")) }; // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -3136,7 +3157,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => param_body, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { @@ -3146,7 +3167,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -3156,7 +3177,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -3185,7 +3206,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -3193,7 +3214,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -3226,7 +3247,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_USER_LOGOUT) => method_not_allowed(), _ if path.matched(paths::ID_USER_USERNAME) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config b/samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config deleted file mode 100644 index b8acc9c00c8c..000000000000 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config +++ /dev/null @@ -1,18 +0,0 @@ -[build] -rustflags = [ - "-W", "missing_docs", # detects missing documentation for public members - - "-W", "trivial_casts", # detects trivial casts which could be removed - - "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - - "-W", "unsafe_code", # usage of `unsafe` code - - "-W", "unused_qualifications", # detects unnecessarily qualified names - - "-W", "unused_extern_crates", # extern crates that are never used - - "-W", "unused_import_braces", # unnecessary braces around an imported item - - "-D", "warnings", # all warnings should be denied -] diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config.toml b/samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config.toml new file mode 100644 index 000000000000..df91f0f117f3 --- /dev/null +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/.cargo/config.toml @@ -0,0 +1,19 @@ +[build] +rustflags = [ + "-W", "missing_docs", # detects missing documentation for public members + + "-W", "trivial_casts", # detects trivial casts which could be removed + + "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed + + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code + + "-W", "unused_qualifications", # detects unnecessarily qualified names + + "-W", "unused_extern_crates", # extern crates that are never used + + "-W", "unused_import_braces", # unnecessary braces around an imported item + + "-D", "warnings", # all warnings should be denied +] diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/ping-bearer-auth/.openapi-generator/FILES index ce2109b1de2e..a4a30ca84661 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -13,6 +13,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/mod.rs src/context.rs diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml b/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml index c8e60c539bba..c956b18efcef 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml @@ -10,73 +10,78 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] cli = [ - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/bin/cli.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/bin/cli.rs index 5838290c33a9..8b33964f40a2 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use log::{debug, info}; // models may be unused if all inputs are primitive types #[allow(unused_imports)] @@ -8,7 +9,6 @@ use ping_bearer_auth::{ PingGetResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -18,48 +18,48 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "ping test", version = "1.0", about = "CLI access to ping test" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, /// Bearer token if used for authentication - #[structopt(env = "PING_BEARER_AUTH_BEARER_TOKEN", hide_env_values = true)] + #[clap(env = "PING_BEARER_AUTH_BEARER_TOKEN", hide_env_values = true)] bearer_token: Option, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { PingGet { }, @@ -100,7 +100,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -151,6 +151,6 @@ async fn main() -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/client/main.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/client/main.rs index e19f556283f4..06c1731a4da4 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/client/main.rs @@ -7,7 +7,7 @@ use futures::{future, Stream, stream}; use ping_bearer_auth::{Api, ApiNoContext, Claims, Client, ContextWrapperExt, models, PingGetResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -30,25 +30,23 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ "PingGet", ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("localhost") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("8080") .help("Port to contact")) .get_matches(); @@ -72,22 +70,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -102,7 +100,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); - match matches.value_of("operation") { + match matches.get_one::("operation") { Some("PingGet") => { let result = rt.block_on(client.ping_get( )); diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/main.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/main.rs index 6b54873a7e94..552e97363a08 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server.rs index 7cac3452a975..77ff0cef3582 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use ping_bearer_auth::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + ping_bearer_auth::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - ping_bearer_auth::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server_auth.rs index 15b1fc1a4443..1e7e5d3187ca 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use ping_bearer_auth::{AuthenticationApi, Claims}; @@ -84,10 +83,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -113,8 +112,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -124,4 +123,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/auth.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/auth.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/client/mod.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/client/mod.rs index 9e6dfec94b3f..4ec23ad74412 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use crate::models; @@ -61,8 +64,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -79,8 +82,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -92,8 +95,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -107,8 +110,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -131,8 +145,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -144,26 +158,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -187,13 +194,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -210,7 +217,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -232,7 +250,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -300,8 +329,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -363,22 +392,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Has> + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn ping_get( &self, @@ -408,7 +434,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -448,9 +474,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/context.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/context.rs index e01187ca3c82..32b419db8b8d 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/context.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs index 495d022b04a3..def1947605e2 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs @@ -30,10 +30,6 @@ pub enum PingGetResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - async fn ping_get( &self, context: &C) -> Result; @@ -45,8 +41,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; async fn ping_get( @@ -70,10 +64,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/mod.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/mod.rs index 04b60fe04545..6742b303e415 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -18,7 +20,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, PingGetResponse @@ -39,15 +41,17 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { api_impl: T, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -59,7 +63,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -67,21 +87,17 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()); future::ok(service) } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -118,23 +134,28 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Has> + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), - ) -> Result, crate::ServiceError> where + req: (Request, C), + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Has> + Send + Sync + 'static { @@ -152,7 +173,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(ref authorization) => authorization, None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) - .body(Body::from("Unauthenticated")) + .body(body_from_str("Unauthenticated")) .expect("Unable to create Authentication Forbidden response")), }; } @@ -160,7 +181,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.ping_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -178,7 +199,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -187,7 +208,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_PING) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/.cargo/config b/samples/server/petstore/rust-server/output/rust-server-test/.cargo/config deleted file mode 100644 index b8acc9c00c8c..000000000000 --- a/samples/server/petstore/rust-server/output/rust-server-test/.cargo/config +++ /dev/null @@ -1,18 +0,0 @@ -[build] -rustflags = [ - "-W", "missing_docs", # detects missing documentation for public members - - "-W", "trivial_casts", # detects trivial casts which could be removed - - "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed - - "-W", "unsafe_code", # usage of `unsafe` code - - "-W", "unused_qualifications", # detects unnecessarily qualified names - - "-W", "unused_extern_crates", # extern crates that are never used - - "-W", "unused_import_braces", # unnecessary braces around an imported item - - "-D", "warnings", # all warnings should be denied -] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/.cargo/config.toml b/samples/server/petstore/rust-server/output/rust-server-test/.cargo/config.toml new file mode 100644 index 000000000000..df91f0f117f3 --- /dev/null +++ b/samples/server/petstore/rust-server/output/rust-server-test/.cargo/config.toml @@ -0,0 +1,19 @@ +[build] +rustflags = [ + "-W", "missing_docs", # detects missing documentation for public members + + "-W", "trivial_casts", # detects trivial casts which could be removed + + "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed + + # unsafe is used in `TokioIo` bridging code copied from `hyper`. + # "-W", "unsafe_code", # usage of `unsafe` code + + "-W", "unused_qualifications", # detects unnecessarily qualified names + + "-W", "unused_extern_crates", # extern crates that are never used + + "-W", "unused_import_braces", # unnecessary braces around an imported item + + "-D", "warnings", # all warnings should be denied +] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/rust-server-test/.openapi-generator/FILES index e27ac4b0b61a..31cb6127bff2 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/rust-server-test/.openapi-generator/FILES @@ -1,4 +1,4 @@ -.cargo/config +.cargo/config.toml .gitignore Cargo.toml README.md @@ -21,6 +21,7 @@ examples/server-key.pem examples/server/main.rs examples/server/server.rs examples/server/server_auth.rs +examples/server/tokio_io.rs src/auth.rs src/client/mod.rs src/context.rs diff --git a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml index f85aaea14517..0f3ab87372b2 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml +++ b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml @@ -10,73 +10,78 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" + "hyper", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] cli = [ - "anyhow", "clap-verbosity-flag", "simple_logger", "structopt", "tokio" + "anyhow", "clap-verbosity-flag", "simple_logger", "tokio" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } -hyper-tls = { version = "0.5", optional = true } +hyper-tls = { version = "0.6", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.9", optional = true } -openssl = {version = "0.10", optional = true } +hyper-openssl = { version = "0.10", optional = true } +openssl = { version = "0.10", optional = true } [dependencies] # Common -async-trait = "0.1.24" +async-trait = "0.1.88" chrono = { version = "0.4", features = ["serde"] } futures = "0.3" -swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] } -log = "0.4.0" +swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", "tls"] } +log = "0.4.27" mime = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -validator = { version = "0.16", features = ["derive"] } +validator = { version = "0.20", features = ["derive"] } # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.14", features = ["full"], optional = true} -serde_ignored = {version = "0.1.1", optional = true} -url = {version = "2.1", optional = true} +bytes = "1.10.1" +http-body-util = "0.1.3" +hyper = { version = "1.6", features = ["full"], optional = true } +hyper-util = { version = "0.1.12", features = ["service"] } +serde_ignored = { version = "0.1.12", optional = true } +url = { version = "2.5", optional = true } # Client-specific +tower-service = "0.3.3" # Server, and client callback-specific -lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "2.1.0", optional = true} -regex = {version = "1.3", optional = true} +lazy_static = { version = "1.5", optional = true } +percent-encoding = { version = "2.3.1", optional = true } +regex = { version = "1.11", optional = true } # CLI-specific anyhow = { version = "1", optional = true } -clap-verbosity-flag = { version = "0.3", optional = true } -simple_logger = { version = "2.0", features = ["stderr"], optional = true } -structopt = { version = "0.3", optional = true } -tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"], optional = true } +clap-verbosity-flag = { version = "3.0", optional = true } +simple_logger = { version = "5.0", features = ["stderr"], optional = true } +tokio = { version = "1.45", features = ["rt-multi-thread", "macros"], optional = true } # Conversion -frunk = { version = "0.4.0", optional = true } -frunk_derives = { version = "0.4.0", optional = true } -frunk_core = { version = "0.4.0", optional = true } +frunk = { version = "0.4.3", optional = true } +frunk_derives = { version = "0.4.3", optional = true } +frunk_core = { version = "0.4.3", optional = true } frunk-enum-derive = { version = "0.3.0", optional = true } frunk-enum-core = { version = "0.3.0", optional = true } # Bearer authentication -jsonwebtoken = { version = "9.3.0", optional = false } +jsonwebtoken = { version = "9.3.1", optional = false } [dev-dependencies] -clap = "2.25" +always_send = "0.1.1" +clap = "4.5" env_logger = "0.11" -tokio = { version = "1.14", features = ["full"] } +tokio = { version = "1.45", features = ["full"] } native-tls = "0.2" +pin-project = "1.1.10" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] tokio-openssl = "0.6" diff --git a/samples/server/petstore/rust-server/output/rust-server-test/bin/cli.rs b/samples/server/petstore/rust-server/output/rust-server-test/bin/cli.rs index e582c479c363..a2ca8e14f9b5 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/bin/cli.rs @@ -1,5 +1,6 @@ //! CLI tool driving the API client use anyhow::{anyhow, Context, Result}; +use clap::Parser; use log::{debug, info}; // models may be unused if all inputs are primitive types #[allow(unused_imports)] @@ -16,7 +17,6 @@ use rust_server_test::{ SoloObjectPostResponse, }; use simple_logger::SimpleLogger; -use structopt::StructOpt; use swagger::{AuthData, ContextBuilder, EmptyContext, Push, XSpanIdString}; type ClientContext = swagger::make_context_ty!( @@ -26,44 +26,44 @@ type ClientContext = swagger::make_context_ty!( XSpanIdString ); -#[derive(StructOpt, Debug)] -#[structopt( +#[derive(Parser, Debug)] +#[clap( name = "rust-server-test", version = "2.3.4", about = "CLI access to rust-server-test" )] struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] operation: Operation, /// Address or hostname of the server hosting this API, including optional port - #[structopt(short = "a", long, default_value = "http://localhost")] + #[clap(short = 'a', long, default_value = "http://localhost")] server_address: String, /// Path to the client private key if using client-side TLS authentication #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-certificate", "server-certificate"]))] + #[clap(long, requires_all(&["client-certificate", "server-certificate"]))] client_key: Option, /// Path to the client's public certificate associated with the private key #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long, requires_all(&["client-key", "server-certificate"]))] + #[clap(long, requires_all(&["client-key", "server-certificate"]))] client_certificate: Option, /// Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] - #[structopt(long)] + #[clap(long)] server_certificate: Option, /// If set, write output to file instead of stdout - #[structopt(short, long)] + #[clap(short, long)] output_file: Option, - #[structopt(flatten)] + #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, } -#[derive(StructOpt, Debug)] +#[derive(Parser, Debug)] enum Operation { AllOfGet { }, @@ -71,7 +71,7 @@ enum Operation { DummyGet { }, DummyPut { - #[structopt(parse(try_from_str = parse_json))] + #[clap(value_parser = parse_json::)] nested_response: models::DummyPutRequest, }, /// Get a file @@ -131,7 +131,7 @@ fn create_client(args: &Cli, context: ClientContext) -> Result Result<()> { - let args = Cli::from_args(); + let args = Cli::parse(); if let Some(log_level) = args.verbosity.log_level() { SimpleLogger::new().with_level(log_level.to_level_filter()).init()?; } @@ -307,6 +307,6 @@ async fn main() -> Result<()> { // May be unused if all inputs are primitive types #[allow(dead_code)] -fn parse_json<'a, T: serde::de::Deserialize<'a>>(json_string: &'a str) -> Result { +fn parse_json(json_string: &str) -> Result { serde_json::from_str(json_string).map_err(|err| anyhow!("Error parsing input: {}", err)) } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs index 99939f148aff..a874d795388f 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs @@ -15,7 +15,7 @@ use rust_server_test::{Api, ApiNoContext, Claims, Client, ContextWrapperExt, mod RawJsonGetResponse, SoloObjectPostResponse, }; -use clap::{App, Arg}; +use clap::{Command, Arg}; // NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels. // See https://docs.rs/env_logger/latest/env_logger/ for more details @@ -38,10 +38,10 @@ use client_auth::build_token; fn main() { env_logger::init(); - let matches = App::new("client") - .arg(Arg::with_name("operation") + let matches = Command::new("client") + .arg(Arg::new("operation") .help("Sets the operation to run") - .possible_values(&[ + .value_parser([ "AllOfGet", "DummyGet", "FileResponseGet", @@ -52,17 +52,15 @@ fn main() { ]) .required(true) .index(1)) - .arg(Arg::with_name("https") + .arg(Arg::new("https") .long("https") .help("Whether to use HTTPS or not")) - .arg(Arg::with_name("host") + .arg(Arg::new("host") .long("host") - .takes_value(true) .default_value("localhost") .help("Hostname to contact")) - .arg(Arg::with_name("port") + .arg(Arg::new("port") .long("port") - .takes_value(true) .default_value("8080") .help("Port to contact")) .get_matches(); @@ -86,22 +84,22 @@ fn main() { b"secret").unwrap(); let auth_data = if !auth_token.is_empty() { - Some(AuthData::Bearer(swagger::auth::Bearer { token: auth_token})) + Some(AuthData::Bearer(auth_token)) } else { // No Bearer-token available, so return None None }; - let is_https = matches.is_present("https"); + let is_https = matches.contains_id("https"); let base_url = format!("{}://{}:{}", if is_https { "https" } else { "http" }, - matches.value_of("host").unwrap(), - matches.value_of("port").unwrap()); + matches.get_one::("host").unwrap(), + matches.get_one::("port").unwrap()); let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default()); - let mut client : Box> = if matches.is_present("https") { + let mut client : Box> = if is_https { // Using Simple HTTPS let client = Box::new(Client::try_new_https(&base_url) .expect("Failed to create HTTPS client")); @@ -116,7 +114,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); - match matches.value_of("operation") { + match matches.get_one::("operation") { Some("AllOfGet") => { let result = rt.block_on(client.all_of_get( )); diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs index 7492252060e2..8475f2ab8c0e 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs @@ -3,12 +3,11 @@ #![allow(missing_docs)] - -use clap::{App, Arg}; +use clap::{Arg, Command}; mod server; mod server_auth; - +mod tokio_io; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -16,13 +15,15 @@ mod server_auth; async fn main() { env_logger::init(); - let matches = App::new("server") - .arg(Arg::with_name("https") - .long("https") - .help("Whether to use HTTPS or not")) + let matches = Command::new("server") + .arg( + Arg::new("https") + .long("https") + .help("Whether to use HTTPS or not"), + ) .get_matches(); let addr = "127.0.0.1:8080"; - server::create(addr, matches.is_present("https")).await; + server::create(addr, matches.contains_id("https")).await; } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs index 00240b2ecdce..37a04e0849f1 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; -use hyper::server::conn::Http; -use hyper::service::Service; +use hyper::server::conn::http1; +use hyper::service::{service_fn, Service}; use log::info; use std::future::Future; use std::marker::PhantomData; @@ -17,26 +17,36 @@ use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; +use crate::tokio_io::TokioIo; + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use rust_server_test::models; +/// Needed because `hyper`'s `service_fn` is sent to a `tokio::task::spawn`, +/// which requires the future to be `'static`. +/// +/// Because `MakeAllowAllAuthenticator` is not `Clone`, this is a shorthand way +/// of creating the `service`. +/// +/// This is not a `fn` because the generics are extremely deeply nested. +macro_rules! create_service { + () => { + { + let server = Server::new(); + let service = MakeService::new(server); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); + rust_server_test::server::context::MakeAddContext::<_, EmptyContext>::new( + service + ) + } + }; +} + /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names pub async fn create(addr: &str, https: bool) { - let addr = addr.parse().expect("Failed to parse bind address"); - - let server = Server::new(); - - let service = MakeService::new(server); - - let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - - #[allow(unused_mut)] - let mut service = - rust_server_test::server::context::MakeAddContext::<_, EmptyContext>::new( - service - ); + let addr: SocketAddr = addr.parse().expect("Failed to parse bind address"); if https { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] @@ -61,14 +71,14 @@ pub async fn create(addr: &str, https: bool) { if let Ok((tcp, _)) = tcp_listener.accept().await { let ssl = Ssl::new(tls_acceptor.context()).unwrap(); let addr = tcp.peer_addr().expect("Unable to get remote address"); - let service = service.call(addr); + let service = create_service!().call(addr); tokio::spawn(async move { let tls = tokio_openssl::SslStream::new(ssl, tcp).map_err(|_| ())?; let service = service.await.map_err(|_| ())?; - Http::new() - .serve_connection(tls, service) + http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), service) .await .map_err(|_| ()) }); @@ -78,11 +88,63 @@ pub async fn create(addr: &str, https: bool) { } else { info!("Starting a server (over http, so no TLS)"); // Using HTTP - hyper::server::Server::bind(&addr).serve(service).await.unwrap() + let listener = TcpListener::bind(&addr).await.unwrap(); + println!("Listening on http://{}", addr); + + loop { + // When an incoming TCP connection is received grab a TCP stream for + // client<->server communication. + // + // Note, this is a .await point, this loop will loop forever but is not a busy loop. The + // .await point allows the Tokio runtime to pull the task off of the thread until the task + // has work to do. In this case, a connection arrives on the port we are listening on and + // the task is woken up, at which point the task is then put back on a thread, and is + // driven forward by the runtime, eventually yielding a TCP stream. + let (tcp_stream, _addr) = listener.accept().await.expect("Failed to accept connection"); + + let service = create_service!(); + let my_service_fn = service_fn(move |req| { + let add_context = service.call(()); + + async move { + let add_context = add_context.await?; + add_context.call(req).await + } + }); + + // Spin up a new task in Tokio so we can continue to listen for new TCP connection on the + // current task without waiting for the processing of the HTTP1 connection we just received + // to finish + tokio::task::spawn(async move { + // Handle the connection from the client using HTTP1 and pass any + // HTTP requests received on that connection to the `hello` function + let result = hyper::server::conn::http1::Builder::new() + .serve_connection(TokioIo::new(tcp_stream), my_service_fn) + // `always_send` is here, because we run into: + // + // ```md + // implementation of `From` is not general enough + // + // `Box<(dyn StdError + std::marker::Send + Sync + 'static)>` must implement `From>`, for any lifetime `'0`... + // ...but it actually implements `From>` + // ``` + // + // This is caused by this rust bug: + // + // + // + .always_send() + .await; + if let Err(err) = result + { + println!("Error serving connection: {:?}", err); + } + }); + } } } -#[derive(Copy, Clone)] +#[derive(Copy)] pub struct Server { marker: PhantomData, } @@ -93,6 +155,14 @@ impl Server { } } +impl Clone for Server { + fn clone(&self) -> Self { + Self { + marker: PhantomData, + } + } +} + use jsonwebtoken::{decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server_auth.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server_auth.rs index 3191e2f7dcb9..097c19ab53c8 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server_auth.rs @@ -1,6 +1,5 @@ use swagger::{ ApiError, - auth::{Basic, Bearer}, Has, XSpanIdString}; use rust_server_test::{AuthenticationApi, Claims}; @@ -84,10 +83,10 @@ fn get_jwt_error_string(error: JwtError::Error) -> String { impl AuthenticationApi for Server where C: Has + Send + Sync { /// Implementation of the method to map a Bearer-token to an Authorization - fn bearer_authorization(&self, bearer: &Bearer) -> Result { - debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}"); + fn bearer_authorization(&self, token: &str) -> Result { + debug!("\tAuthorizationApi: Received Bearer-token, {token:#?}"); - match extract_token_data(&bearer.token, b"secret") { + match extract_token_data(token, b"secret") { Ok(auth_data) => { debug!("\tUnpack auth_data as: {auth_data:#?}"); let authorization = build_authorization(auth_data.claims); @@ -113,8 +112,8 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } /// Implementation of the method to map a basic authentication (username and password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result { - debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}"); + fn basic_authorization(&self, username: &str, _password: &str) -> Result { + debug!("\tAuthorizationApi: Received Basic-token, {username}"); // TODO: insert the logic to map received apikey to the set of claims let claims = full_permission_claim(); @@ -124,4 +123,3 @@ impl AuthenticationApi for Server where C: Has + Send + Syn } } - diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/tokio_io.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/tokio_io.rs new file mode 100644 index 000000000000..f2b81d16b225 --- /dev/null +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/tokio_io.rs @@ -0,0 +1,147 @@ +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + +use pin_project::pin_project; + +#[pin_project] +#[derive(Debug)] +pub struct TokioIo { + #[pin] + inner: T, +} + +impl TokioIo { + pub fn new(inner: T) -> Self { + Self { inner } + } +} + +impl hyper::rt::Read for TokioIo +where + T: tokio::io::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let n = unsafe { + let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); + match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { + Poll::Ready(Ok(())) => tbuf.filled().len(), + other => return other, + } + }; + + unsafe { + buf.advance(n); + } + Poll::Ready(Ok(())) + } +} + +impl hyper::rt::Write for TokioIo +where + T: tokio::io::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + tokio::io::AsyncWrite::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) + } +} + +impl tokio::io::AsyncRead for TokioIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + tbuf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + //let init = tbuf.initialized().len(); + let filled = tbuf.filled().len(); + let sub_filled = unsafe { + let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); + + match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { + Poll::Ready(Ok(())) => buf.filled().len(), + other => return other, + } + }; + + let n_filled = filled + sub_filled; + // At least sub_filled bytes had to have been initialized. + let n_init = sub_filled; + unsafe { + tbuf.assume_init(n_init); + tbuf.set_filled(n_filled); + } + + Poll::Ready(Ok(())) + } +} + +impl tokio::io::AsyncWrite for TokioIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.project().inner, cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + hyper::rt::Write::poll_flush(self.project().inner, cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.project().inner, cx) + } + + fn is_write_vectored(&self) -> bool { + hyper::rt::Write::is_write_vectored(&self.inner) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) + } +} diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/auth.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/auth.rs index d2b1481eeb81..804b96d8960b 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/auth.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/auth.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::server::Authorization; use serde::{Deserialize, Serialize}; -use swagger::{ApiError, auth::{Basic, Bearer}}; +use swagger::{ApiError, auth::AuthData}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { @@ -17,14 +17,14 @@ pub struct Claims { pub trait AuthenticationApi { /// Method should be implemented (see example-code) to map Bearer-token to an Authorization - fn bearer_authorization(&self, token: &Bearer) -> Result; + fn bearer_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map ApiKey to an Authorization fn apikey_authorization(&self, token: &str) -> Result; /// Method should be implemented (see example-code) to map Basic (Username:password) to an Authorization - fn basic_authorization(&self, basic: &Basic) -> Result; -} + fn basic_authorization(&self, username: &str, password: &str) -> Result; +} // Implement it for AllowAllAuthenticator (dummy is needed, but should not used as we have Bearer authorization) use swagger::auth::{AllowAllAuthenticator, RcBound, Scopes}; @@ -46,7 +46,7 @@ where RC::Result: Send + 'static { /// Get method to map Bearer-token to an Authorization - fn bearer_authorization(&self, _token: &Bearer) -> Result { + fn bearer_authorization(&self, _token: &str) -> Result { Ok(dummy_authorization()) } @@ -56,7 +56,7 @@ where } /// Get method to map basic token to an Authorization - fn basic_authorization(&self, _basic: &Basic) -> Result { + fn basic_authorization(&self, _username: &str, _password: &str) -> Result { Ok(dummy_authorization()) } } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs index a88ea9dea0ae..7afdfcbccdbb 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs @@ -1,7 +1,9 @@ use async_trait::async_trait; +use bytes::Bytes; use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; +use http_body_util::{combinators::BoxBody, Full}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Request, Response, service::Service, Uri}; +use hyper::{body::{Body, Incoming}, Request, Response, service::Service, Uri}; use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; @@ -18,6 +20,7 @@ use std::string::ToString; use std::task::{Context, Poll}; use swagger::{ApiError, AuthData, BodyExt, Connector, DropContextService, Has, XSpanIdString}; use url::form_urlencoded; +use tower_service::Service as _; use crate::models; @@ -69,8 +72,8 @@ fn into_base_path(input: impl TryInto, /// A client that implements the API by making HTTP calls out to a server. pub struct Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -87,8 +90,8 @@ pub struct Client where impl fmt::Debug for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -100,8 +103,8 @@ impl fmt::Debug for Client where impl Clone for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -115,8 +118,19 @@ impl Clone for Client where } } -impl Client, C>, C> where - Connector: hyper::client::connect::Connect + Clone + Send + Sync + 'static, +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + Connector, + BoxBody + > + >, + C + >, + C +> where + Connector: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static, C: Clone + Send + Sync + 'static, { /// Create a client with a custom implementation of hyper::client::Connect. @@ -139,8 +153,8 @@ impl Client Result { - let client_service = hyper::client::Client::builder().build(connector); - let client_service = DropContextService::new(client_service); + let client_service = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector); + let client_service = DropContextService::new(hyper_util::service::TowerToHyperService::new(client_service)); Ok(Self { client_service, @@ -152,26 +166,19 @@ impl Client), - Https(hyper::client::Client), + Http(hyper_util::client::legacy::Client>), + Https(hyper_util::client::legacy::Client>), } -impl Service> for HyperClient { - type Response = Response; - type Error = hyper::Error; - type Future = hyper::client::ResponseFuture; - - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - match self { - HyperClient::Http(client) => client.poll_ready(cx), - HyperClient::Https(client) => client.poll_ready(cx), - } - } +impl Service>> for HyperClient { + type Response = Response; + type Error = hyper_util::client::legacy::Error; + type Future = hyper_util::client::legacy::ResponseFuture; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request>) -> Self::Future { match self { - HyperClient::Http(client) => client.call(req), - HyperClient::Https(client) => client.call(req) + HyperClient::Http(client) => client.request(req), + HyperClient::Https(client) => client.request(req) } } } @@ -195,13 +202,13 @@ impl Client, C> where let client_service = match scheme.as_str() { "http" => { - HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build())) }, "https" => { let connector = connector.https() .build() .map_err(ClientInitError::SslError)?; - HyperClient::Https(hyper::client::Client::builder().build(connector)) + HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector)) }, _ => { return Err(ClientInitError::InvalidScheme); @@ -218,7 +225,18 @@ impl Client, C> where } } -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create an HTTP client. @@ -240,7 +258,18 @@ type HttpsConnector = hyper_tls::HttpsConnector; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] type HttpsConnector = hyper_openssl::HttpsConnector; -impl Client, C>, C> where +impl Client< + DropContextService< + hyper_util::service::TowerToHyperService< + hyper_util::client::legacy::Client< + HttpsConnector, + BoxBody + > + >, + C + >, + C +> where C: Clone + Send + Sync + 'static { /// Create a client with a TLS connection to the server @@ -308,8 +337,8 @@ impl Client, C impl Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Clone + Send + Sync + 'static @@ -371,22 +400,19 @@ impl Error for ClientInitError { } } +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + #[async_trait] impl Api for Client where S: Service< - (Request, C), - Response=Response> + Clone + Sync + Send + 'static, + (Request>, C), + Response=Response> + Clone + Sync + Send + 'static, S::Future: Send + 'static, S::Error: Into + fmt::Display, C: Has + Clone + Send + Sync + 'static, { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - match self.client_service.clone().poll_ready(cx) { - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), - Poll::Pending => Poll::Pending, - } - } async fn all_of_get( &self, @@ -416,7 +442,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -433,9 +459,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -449,9 +476,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -495,7 +522,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -517,9 +544,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -564,7 +591,7 @@ impl Api for Client where let mut request = match Request::builder() .method("PUT") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -572,7 +599,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_nested_response).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -597,9 +624,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -643,7 +670,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -660,9 +687,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -676,9 +704,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -722,7 +750,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -739,9 +767,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -754,9 +783,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -801,7 +830,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -809,7 +838,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = param_body; - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "text/html"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -829,9 +858,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -844,9 +874,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -891,7 +921,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -899,7 +929,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = param_value; - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/yaml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -924,9 +954,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -970,7 +1000,7 @@ impl Api for Client where let mut request = match Request::builder() .method("GET") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -987,9 +1017,10 @@ impl Api for Client where match response.status().as_u16() { 200 => { let body = response.into_body(); - let body = body - .into_raw() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = http_body_util::BodyExt::collect(body) + .await + .map(|f| f.to_bytes().to_vec()) + .map_err(|e| ApiError(format!("Failed to read response: {}", e)))?; let body = str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; @@ -1003,9 +1034,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, @@ -1050,7 +1081,7 @@ impl Api for Client where let mut request = match Request::builder() .method("POST") .uri(uri) - .body(Body::empty()) { + .body(BoxBody::new(http_body_util::Empty::new())) { Ok(req) => req, Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; @@ -1058,7 +1089,7 @@ impl Api for Client where // Consumes basic body // Body parameter let body = serde_json::to_string(¶m_value).expect("impossible to fail to serialize"); - *request.body_mut() = Body::from(body); + *request.body_mut() = body_from_string(body); let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { @@ -1083,9 +1114,9 @@ impl Api for Client where } code => { let headers = response.headers().clone(); - let body = response.into_body() - .take(100) - .into_raw().await; + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .map(|f| f.to_bytes().to_vec()); Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, headers, diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs index ee8e118587bb..826c5e146ec7 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs @@ -6,7 +6,7 @@ use std::default::Default; use std::io; use std::marker::PhantomData; use std::task::{Poll, Context}; -use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; +use swagger::auth::{AuthData, Authorization, Scopes}; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::{Api, AuthenticationApi}; use log::error; @@ -30,6 +30,18 @@ where } } +impl Clone for MakeAddContext +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + // Make a service that adds context. impl Service for MakeAddContext @@ -46,11 +58,7 @@ where type Response = AddContext; type Future = BoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, target: Target) -> Self::Future { let service = self.inner.call(target); Box::pin(async move { @@ -96,12 +104,7 @@ impl Service> for AddContext) -> Poll> { - self.inner.poll_ready(cx) - } - - - fn call(&mut self, request: Request) -> Self::Future { + fn call(&self, request: Request) -> Self::Future { let context = A::default().push(XSpanIdString::get_or_generate(&request)); let headers = request.headers(); diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs index 3adabd148d80..9183faf7d34f 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs @@ -83,10 +83,6 @@ pub enum SoloObjectPostResponse { #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - fn poll_ready(&self, _cx: &mut Context) -> Poll>> { - Poll::Ready(Ok(())) - } - async fn all_of_get( &self, context: &C) -> Result; @@ -139,8 +135,6 @@ pub trait Api { #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { - fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn context(&self) -> &C; async fn all_of_get( @@ -205,10 +199,6 @@ impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T #[async_trait] impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { - fn poll_ready(&self, cx: &mut Context) -> Poll> { - self.api().poll_ready(cx) - } - fn context(&self) -> &C { ContextWrapper::context(self) } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs index d2e153e4ac52..464e6b934fbb 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs @@ -1,10 +1,12 @@ +use bytes::Bytes; use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; -use hyper::{Request, Response, StatusCode, Body, HeaderMap}; +use http_body_util::{combinators::BoxBody, Full}; +use hyper::{body::{Body, Incoming}, HeaderMap, Request, Response, StatusCode}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::error::Error; +use std::{convert::Infallible, error::Error}; use std::future::Future; use std::marker::PhantomData; use std::task::{Context, Poll}; @@ -18,7 +20,7 @@ use crate::{models, header, AuthenticationApi}; pub use crate::context; -type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; +type ServiceFuture = BoxFuture<'static, Result>, crate::ServiceError>>; use crate::{Api, AllOfGetResponse, @@ -61,15 +63,17 @@ mod paths { } -pub struct MakeService where +pub struct MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { api_impl: T, - marker: PhantomData, + marker: PhantomData<(C, Target)>, } -impl MakeService where +impl MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -81,7 +85,23 @@ impl MakeService where } } -impl hyper::service::Service for MakeService where +impl Clone for MakeService +where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ + fn clone(&self) -> Self { + Self { + api_impl: self.api_impl.clone(), + marker: PhantomData, + } + } +} + +// `MakeService` itself doesn't take the request type (so we use `()`), +// but we need the `Target` type parameter to track the inner hyper `Service`. +impl hyper::service::Service<()> for MakeService +where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -89,21 +109,17 @@ impl hyper::service::Service for MakeService where type Error = crate::ServiceError; type Future = future::Ready>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, target: Target) -> Self::Future { + fn call(&self, (): ()) -> Self::Future { let service = Service::new(self.api_impl.clone()); future::ok(service) } } -fn method_not_allowed() -> Result, crate::ServiceError> { +fn method_not_allowed() -> Result>, crate::ServiceError> { Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Method Not Allowed response") ) } @@ -140,23 +156,28 @@ impl Clone for Service where } } -impl hyper::service::Service<(Request, C)> for Service where +fn body_from_string(s: String) -> BoxBody { + BoxBody::new(Full::new(Bytes::from(s))) +} + +fn body_from_str(s: &str) -> BoxBody { + BoxBody::new(Full::new(Bytes::copy_from_slice(s.as_bytes()))) +} + +impl hyper::service::Service<(Request, C)> for Service where T: Api + Clone + Send + Sync + 'static, C: Has + Send + Sync + 'static { - type Response = Response; + type Response = Response>; type Error = crate::ServiceError; type Future = ServiceFuture; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.api_impl.poll_ready(cx) - } - - fn call(&mut self, req: (Request, C)) -> Self::Future { + fn call(&self, req: (Request, C)) -> Self::Future { async fn run( mut api_impl: T, - req: (Request, C), - ) -> Result, crate::ServiceError> where + req: (Request, C), + ) -> Result>, crate::ServiceError> + where T: Api + Clone + Send + 'static, C: Has + Send + Sync + 'static { @@ -172,7 +193,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.all_of_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -190,7 +211,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for */*")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -198,7 +219,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -210,7 +231,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.dummy_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -228,7 +249,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -240,7 +261,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -253,7 +274,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_nested_response) => param_nested_response, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter nested_response - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter nested_response - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter nested_response due to schema")), } } else { @@ -263,7 +284,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_nested_response) => param_nested_response, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter nested_response")) + .body(body_from_str("Missing required body parameter nested_response")) .expect("Unable to create Bad Request response for missing body parameter nested_response")), }; @@ -272,7 +293,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_nested_response, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -296,7 +317,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -304,7 +325,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -314,7 +335,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.file_response_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -332,7 +353,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/json")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -340,7 +361,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -352,7 +373,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.get_structured_yaml( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -370,7 +391,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for application/yaml")); // Plain text Body let body = body; - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -378,7 +399,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -390,7 +411,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let param_body: Option = if !body.is_empty() { @@ -398,7 +419,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_body) => Some(param_body), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter body due to UTF-8")), } } else { @@ -408,7 +429,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_body) => param_body, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter body")) + .body(body_from_str("Missing required body parameter body")) .expect("Unable to create Bad Request response for missing body parameter body")), }; @@ -417,7 +438,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_body, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -435,7 +456,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for text/html")); // Plain text Body let body = body; - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -443,7 +464,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -451,7 +472,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -461,7 +482,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let param_value: Option = if !body.is_empty() { @@ -469,7 +490,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_value) => Some(param_value), Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter value - not valid UTF-8: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter value - not valid UTF-8: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter value due to UTF-8")), } } else { @@ -479,7 +500,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_value) => param_value, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter value")) + .body(body_from_str("Missing required body parameter value")) .expect("Unable to create Bad Request response for missing body parameter value")), }; @@ -488,7 +509,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_value, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -506,7 +527,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -514,7 +535,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -524,7 +545,7 @@ impl hyper::service::Service<(Request, C)> for Service where let result = api_impl.raw_json_get( &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -542,7 +563,7 @@ impl hyper::service::Service<(Request, C)> for Service where .expect("Unable to create Content-Type header for */*")); // JSON Body let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); - *response.body_mut() = Body::from(body); + *response.body_mut() = BoxBody::new(Full::new(Bytes::from(body))); }, }, @@ -550,7 +571,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -562,7 +583,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Handle body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - let result = body.into_raw().await; + let result = http_body_util::BodyExt::collect(body).await.map(|f| f.to_bytes().to_vec()); match result { Ok(body) => { let mut unused_elements : Vec = vec![]; @@ -575,7 +596,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(param_value) => param_value, Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Couldn't parse body parameter value - doesn't match schema: {}", e))) + .body(body_from_string(format!("Couldn't parse body parameter value - doesn't match schema: {}", e))) .expect("Unable to create Bad Request response for invalid body parameter value due to schema")), } } else { @@ -585,7 +606,7 @@ impl hyper::service::Service<(Request, C)> for Service where Some(param_value) => param_value, None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("Missing required body parameter value")) + .body(body_from_str("Missing required body parameter value")) .expect("Unable to create Bad Request response for missing body parameter value")), }; @@ -594,7 +615,7 @@ impl hyper::service::Service<(Request, C)> for Service where param_value, &context ).await; - let mut response = Response::new(Body::empty()); + let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().as_str()) @@ -618,7 +639,7 @@ impl hyper::service::Service<(Request, C)> for Service where // Application code returned an error. This should not happen, as the implementation should // return a valid response. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - *response.body_mut() = Body::from("An internal error occurred"); + *response.body_mut() = body_from_str("An internal error occurred"); }, } @@ -626,7 +647,7 @@ impl hyper::service::Service<(Request, C)> for Service where }, Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from(format!("Unable to read body: {}", e))) + .body(body_from_string(format!("Unable to read body: {}", e))) .expect("Unable to create Bad Request response due to unable to read body")), } }, @@ -640,7 +661,7 @@ impl hyper::service::Service<(Request, C)> for Service where _ if path.matched(paths::ID_RAW_JSON) => method_not_allowed(), _ if path.matched(paths::ID_SOLO_OBJECT) => method_not_allowed(), _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) - .body(Body::empty()) + .body(BoxBody::new(http_body_util::Empty::new())) .expect("Unable to create Not Found response")) } } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/server/server_auth.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/server/server_auth.rs index ba78eb2f3f5d..d63030b86840 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/server/server_auth.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/server/server_auth.rs @@ -2,17 +2,17 @@ use super::Service; use crate::{Api, AuthenticationApi}; use swagger::{ ApiError, - Authorization, - auth::{Basic, Bearer}, - Has, - XSpanIdString}; + Authorization, + Has, + XSpanIdString +}; impl AuthenticationApi for Service where T: Api + Clone + Send + 'static + AuthenticationApi, C: Has + Has> + Send + Sync + 'static { /// Passthrough of the task to the api-implementation - fn bearer_authorization(&self, token: &Bearer) -> Result { + fn bearer_authorization(&self, token: &str) -> Result { self.api_impl.bearer_authorization(token) } @@ -22,7 +22,7 @@ C: Has + Has> + Send + Sync + 'static { } /// Passthrough of the task to the api-implementation - fn basic_authorization(&self, basic: &Basic) -> Result { - self.api_impl.basic_authorization(basic) + fn basic_authorization(&self, username: &str, password: &str) -> Result { + self.api_impl.basic_authorization(username, password) } }