diff --git a/Cargo.lock b/Cargo.lock index 7f21560d..e615556d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3680,7 +3680,7 @@ dependencies = [ [[package]] name = "volo-http" -version = "0.2.12" +version = "0.2.13" dependencies = [ "ahash", "async-broadcast", diff --git a/volo-http/Cargo.toml b/volo-http/Cargo.toml index 61fd951b..72dc7f52 100644 --- a/volo-http/Cargo.toml +++ b/volo-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "volo-http" -version = "0.2.12" +version = "0.2.13" edition.workspace = true homepage.workspace = true repository.workspace = true diff --git a/volo-http/src/client/meta.rs b/volo-http/src/client/meta.rs index d417f031..6babaef6 100644 --- a/volo-http/src/client/meta.rs +++ b/volo-http/src/client/meta.rs @@ -1,4 +1,4 @@ -use std::{error::Error, time::Duration}; +use std::error::Error; use http_body::Body; use motore::service::Service; @@ -6,7 +6,7 @@ use volo::context::Context; use crate::{ context::ClientContext, - error::client::{status_error, timeout, ClientError}, + error::client::{status_error, ClientError}, request::ClientRequest, response::ClientResponse, }; @@ -14,18 +14,11 @@ use crate::{ #[derive(Clone)] pub struct MetaService { inner: S, - config: MetaServiceConfig, -} - -#[derive(Clone)] -pub(super) struct MetaServiceConfig { - pub default_timeout: Option, - pub fail_on_error_status: bool, } impl MetaService { - pub(super) fn new(inner: S, config: MetaServiceConfig) -> Self { - Self { inner, config } + pub(super) fn new(inner: S) -> Self { + Self { inner } } } @@ -47,27 +40,23 @@ where cx: &mut ClientContext, req: ClientRequest, ) -> Result { - let request_timeout = cx - .rpc_info() - .config() - .timeout - .or(self.config.default_timeout); + let config = cx.rpc_info().config().to_owned(); let fut = self.inner.call(cx, req); - let res = match request_timeout { + let res = match config.timeout { Some(duration) => { let sleep = tokio::time::sleep(duration); tokio::select! { res = fut => res, _ = sleep => { tracing::error!("[Volo-HTTP]: request timeout."); - return Err(timeout()); + return Err(crate::error::client::timeout()); } } } None => fut.await, }; - if !self.config.fail_on_error_status { + if !config.fail_on_error_status { return res; } diff --git a/volo-http/src/client/mod.rs b/volo-http/src/client/mod.rs index b2ceb6db..8dcbf899 100644 --- a/volo-http/src/client/mod.rs +++ b/volo-http/src/client/mod.rs @@ -33,7 +33,7 @@ use self::{ callopt::CallOpt, dns::parse_target, loadbalance::{DefaultLB, DefaultLBService, LbConfig}, - meta::{MetaService, MetaServiceConfig}, + meta::MetaService, target::TargetParser, transport::{ClientConfig, ClientTransport, ClientTransportConfig}, }; @@ -94,11 +94,11 @@ pub struct ClientBuilder { /// This is unstable now and may be changed in the future. #[doc(hidden)] pub struct BuilderConfig { - timeout: Option, - stat_enable: bool, - fail_on_error_status: bool, + pub timeout: Option, + pub stat_enable: bool, + pub fail_on_error_status: bool, #[cfg(feature = "__tls")] - disable_tls: bool, + pub disable_tls: bool, } impl Default for BuilderConfig { @@ -605,20 +605,20 @@ impl ClientBuilder { } /// Set the maximum idle time for a connection. - pub fn set_connect_timeout(&mut self, timeout: Option) -> &mut Self { - self.connector.set_connect_timeout(timeout); + pub fn set_connect_timeout(&mut self, timeout: Duration) -> &mut Self { + self.connector.set_connect_timeout(Some(timeout)); self } /// Set the maximum idle time for reading data from the connection. - pub fn set_read_timeout(&mut self, timeout: Option) -> &mut Self { - self.connector.set_read_timeout(timeout); + pub fn set_read_timeout(&mut self, timeout: Duration) -> &mut Self { + self.connector.set_read_timeout(Some(timeout)); self } /// Set the maximum idle time for writing data to the connection. - pub fn set_write_timeout(&mut self, timeout: Option) -> &mut Self { - self.connector.set_write_timeout(timeout); + pub fn set_write_timeout(&mut self, timeout: Duration) -> &mut Self { + self.connector.set_write_timeout(Some(timeout)); self } @@ -626,8 +626,8 @@ impl ClientBuilder { /// /// The whole request includes connecting, writting, and reading the whole HTTP protocol /// headers (without reading response body). - pub fn set_request_timeout(&mut self, timeout: Option) -> &mut Self { - self.builder_config.timeout = timeout; + pub fn set_request_timeout(&mut self, timeout: Duration) -> &mut Self { + self.builder_config.timeout = Some(timeout); self } @@ -648,10 +648,6 @@ impl ClientBuilder { #[cfg(feature = "__tls")] disable_tls: self.builder_config.disable_tls, }; - let meta_config = MetaServiceConfig { - default_timeout: self.builder_config.timeout, - fail_on_error_status: self.builder_config.fail_on_error_status, - }; let transport = ClientTransport::new( self.http_config, transport_config, @@ -659,7 +655,7 @@ impl ClientBuilder { #[cfg(feature = "__tls")] self.tls_config.unwrap_or_default(), ); - let meta_service = MetaService::new(transport, meta_config); + let meta_service = MetaService::new(transport); let service = self.outer_layer.layer( self.mk_lb .make() @@ -671,18 +667,22 @@ impl ClientBuilder { } else { self.caller_name }; - if !caller_name.is_empty() && self.headers.get(header::USER_AGENT).is_none() { self.headers.insert( header::USER_AGENT, HeaderValue::from_str(caller_name.as_str()).expect("Invalid caller name"), ); } + let config = Config { + timeout: self.builder_config.timeout, + fail_on_error_status: self.builder_config.fail_on_error_status, + }; let client_inner = ClientInner { caller_name, callee_name: self.callee_name, default_target: self.target, + default_config: config, default_call_opt: self.call_opt, target_parser: self.target_parser, headers: self.headers, @@ -699,6 +699,7 @@ struct ClientInner { caller_name: FastStr, callee_name: FastStr, default_target: Target, + default_config: Config, default_call_opt: Option, target_parser: TargetParser, headers: HeaderMap, @@ -876,8 +877,9 @@ impl Client { cx.rpc_info_mut().callee_mut().set_service_name(callee_name); (self.inner.target_parser)(target, call_opt, cx.rpc_info_mut().callee_mut()); - let config = Config { timeout }; - cx.rpc_info_mut().set_config(config); + let config = cx.rpc_info_mut().config_mut(); + config.clone_from(&self.inner.default_config); + config.timeout = timeout.or(config.timeout); self.call(&mut cx, request).await } diff --git a/volo-http/src/context/client.rs b/volo-http/src/context/client.rs index 84dbdff8..e5d90adc 100644 --- a/volo-http/src/context/client.rs +++ b/volo-http/src/context/client.rs @@ -64,6 +64,8 @@ impl ClientStats { pub struct Config { /// Timeout of the whole request pub timeout: Option, + /// Return `Err` if status code of response is 4XX or 5XX + pub fail_on_error_status: bool, } impl Reusable for Config {