// file: crates/ksp-offchain-transport-lib/src/http_settings.rs // version: 3 //! Crate-wide bounded HTTP runtime settings shared by off-chain capability families. const DEFAULT_CONNECT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5); const DEFAULT_MAX_RESPONSE_BODY_BYTES: usize = 1_048_576; const DEFAULT_REQUEST_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); #[cfg(test)] const MAX_CONNECT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30); #[cfg(test)] const MAX_REQUEST_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(120); #[cfg(test)] const MAX_RESPONSE_BODY_BYTES: usize = 4_194_304; /// Crate-internal HTTP client settings with defensive hard bounds. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub(crate) struct HttpClientSettings { connect_timeout: std::time::Duration, max_response_body_bytes: usize, request_timeout: std::time::Duration, } impl crate::HttpClientSettings { /// Creates one validated HTTP settings value for deterministic settings tests until runtime configuration consumes this constructor. #[cfg(test)] pub(crate) fn new( connect_timeout: std::time::Duration, request_timeout: std::time::Duration, max_response_body_bytes: usize, ) -> ksp_core_lib::Result { if connect_timeout.is_zero() || connect_timeout > MAX_CONNECT_TIMEOUT { return invalid_http_settings("HTTP connect timeout is outside the supported bounds", "connect_timeout"); } if request_timeout.is_zero() || request_timeout > MAX_REQUEST_TIMEOUT { return invalid_http_settings("HTTP request timeout is outside the supported bounds", "request_timeout"); } if connect_timeout > request_timeout { return invalid_http_settings("HTTP connect timeout cannot exceed the total request timeout", "connect_timeout"); } if max_response_body_bytes == 0 || max_response_body_bytes > MAX_RESPONSE_BODY_BYTES { return invalid_http_settings("HTTP response-body limit is outside the supported bounds", "max_response_body_bytes"); } return std::result::Result::Ok(Self { connect_timeout, max_response_body_bytes, request_timeout }); } /// Returns the bounded connect timeout. #[must_use] pub(crate) const fn connect_timeout(&self) -> std::time::Duration { return self.connect_timeout; } /// Returns the maximum decoded response body accepted before JSON parsing. #[must_use] pub(crate) const fn max_response_body_bytes(&self) -> usize { return self.max_response_body_bytes; } /// Returns the end-to-end request timeout. #[must_use] pub(crate) const fn request_timeout(&self) -> std::time::Duration { return self.request_timeout; } } impl std::default::Default for crate::HttpClientSettings { fn default() -> Self { return Self { connect_timeout: DEFAULT_CONNECT_TIMEOUT, max_response_body_bytes: DEFAULT_MAX_RESPONSE_BODY_BYTES, request_timeout: DEFAULT_REQUEST_TIMEOUT, }; } } #[cfg(test)] fn invalid_http_settings(message: &str, field: &'static str) -> ksp_core_lib::Result { ksp_logging_lib::warn!(target: crate::TRACING_TARGET, field = field, "rejected invalid off-chain HTTP client settings"); return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_HTTP_SETTINGS_INVALID, message).with_context("field", field)); } #[cfg(test)] #[path = "../unit_tests/http_settings.rs"] mod tests;