diff --git a/ylong_http_client/src/async_impl/client.rs b/ylong_http_client/src/async_impl/client.rs index e0c2268842ae935462efd58643573b59641628f9..3b408dd80a3e6d07dded25b729088436c5d5bf31 100644 --- a/ylong_http_client/src/async_impl/client.rs +++ b/ylong_http_client/src/async_impl/client.rs @@ -24,6 +24,8 @@ use crate::error::HttpClientError; use crate::runtime::timeout; #[cfg(feature = "__c_openssl")] use crate::util::c_openssl::verify::PubKeyPins; +#[cfg(all(target_os = "linux", feature = "ylong_base"))] +use crate::util::config::FchownConfig; use crate::util::config::{ ClientConfig, ConnectorConfig, HttpConfig, HttpVersion, Proxy, Redirect, Timeout, }; @@ -257,6 +259,10 @@ pub struct ClientBuilder { /// Options and flags that is related to `Proxy`. proxies: Proxies, + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + /// Fchown configuration. + fchown: Option, + interceptors: Arc, /// Options and flags that is related to `TLS`. @@ -279,6 +285,8 @@ impl ClientBuilder { http: HttpConfig::default(), client: ClientConfig::default(), proxies: Proxies::default(), + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + fchown: None, interceptors: Arc::new(IdleInterceptor), #[cfg(feature = "__tls")] tls: crate::util::TlsConfig::builder(), @@ -352,6 +360,23 @@ impl ClientBuilder { self } + /// Sets a `Fchown` for this client. + /// + /// Default will not set the owner of the file descriptor. + /// + /// # Examples + /// + /// ``` + /// use ylong_http_client::async_impl::ClientBuilder; + /// + /// let builder = ClientBuilder::new().sockets_owner(1000, 1000); + /// ``` + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + pub fn sockets_owner(mut self, uid: u32, gid: u32) -> Self { + self.fchown = Some(FchownConfig::new(uid, gid)); + self + } + /// Sets retry times for this client. /// /// The Retry is the number of times the client will retry the request if @@ -441,6 +466,8 @@ impl ClientBuilder { let config = ConnectorConfig { proxies: self.proxies, + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + fchown: self.fchown, #[cfg(feature = "__tls")] tls: tls_builder.build()?, }; diff --git a/ylong_http_client/src/async_impl/connector/mod.rs b/ylong_http_client/src/async_impl/connector/mod.rs index a581566e54c1e53dea7d52e68448527890e4571d..04d72050569c9c7b96daa4293c166b6126985b1c 100644 --- a/ylong_http_client/src/async_impl/connector/mod.rs +++ b/ylong_http_client/src/async_impl/connector/mod.rs @@ -156,9 +156,16 @@ mod tls { .map(|host| host.to_string()) .unwrap_or_else(|| "no host in uri".to_string()); + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + let fchown = self.config.fchown.clone(); match *uri.scheme().unwrap() { Scheme::HTTP => Box::pin(async move { let stream = tcp_stream(&addr).await?; + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + if let Some(fchown) = fchown { + stream.fchown(fchown.uid, fchown.gid).unwrap(); + } + let local = stream.local_addr()?; let peer = stream.peer_addr()?; let detail = ConnDetail { @@ -176,6 +183,10 @@ mod tls { let config = self.config.tls.clone(); Box::pin(async move { let mut tcp = tcp_stream(&addr).await?; + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + if let Some(fchown) = fchown { + tcp.fchown(fchown.uid, fchown.gid).unwrap(); + } let local = tcp.local_addr()?; let peer = tcp.peer_addr()?; if is_proxy { diff --git a/ylong_http_client/src/util/config/connector.rs b/ylong_http_client/src/util/config/connector.rs index ec40566c774034c1c0e8109f8f9d7760f733de07..80de0eeb2dc3b380332b1ef0120ca3c2ce9cbd93 100644 --- a/ylong_http_client/src/util/config/connector.rs +++ b/ylong_http_client/src/util/config/connector.rs @@ -13,12 +13,17 @@ //! Connector configure module. + #[cfg(all(target_os = "linux", feature = "ylong_base"))] +use super::FchownConfig; use crate::util::proxy::Proxies; #[derive(Default)] pub(crate) struct ConnectorConfig { pub(crate) proxies: Proxies, + #[cfg(all(target_os = "linux", feature = "ylong_base"))] + pub(crate) fchown: Option, + #[cfg(feature = "__tls")] pub(crate) tls: crate::util::TlsConfig, } diff --git a/ylong_http_client/src/util/config/fchown.rs b/ylong_http_client/src/util/config/fchown.rs new file mode 100644 index 0000000000000000000000000000000000000000..73c23e3233e8b689cab2d3a8437ad321a08b3afc --- /dev/null +++ b/ylong_http_client/src/util/config/fchown.rs @@ -0,0 +1,26 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use libc::{gid_t, uid_t}; + +#[derive(Clone, Default)] +pub(crate) struct FchownConfig { + pub(crate) uid: uid_t, + pub(crate) gid: gid_t, +} + +impl FchownConfig { + pub(crate) fn new(uid: uid_t, gid: gid_t) -> Self { + Self { uid, gid } + } +} diff --git a/ylong_http_client/src/util/config/mod.rs b/ylong_http_client/src/util/config/mod.rs index 66b79212321630267a763e645d4628ae8c140150..3e766d5af30386017bf3062fe4a6eced19de18f6 100644 --- a/ylong_http_client/src/util/config/mod.rs +++ b/ylong_http_client/src/util/config/mod.rs @@ -30,3 +30,7 @@ pub(crate) use tls::{AlpnProtocol, AlpnProtocolList}; pub use tls::{CertVerifier, ServerCerts}; #[cfg(feature = "tls_rust_ssl")] pub use tls::{Certificate, PrivateKey, TlsConfig, TlsConfigBuilder, TlsFileType, TlsVersion}; + #[cfg(all(target_os = "linux", feature = "ylong_base"))] +mod fchown; + #[cfg(all(target_os = "linux", feature = "ylong_base"))] +pub(crate) use fchown::FchownConfig;