use std::time::Duration; use anyhow::{bail, ensure}; use http::{Extensions, HeaderMap, HeaderName, StatusCode}; use crate::{status::ConnectStatus, Status}; const GRPC_PREFIX: &str = "grpc-"; const GRPC_TIMEOUT: &str = "grpc-timeout"; // Timeout → "connect-timeout-ms" Timeout-Milliseconds const CONNECT_TIMEOUT_MS: &str = "connect-timeout-ms"; // Timeout-Milliseconds → {positive integer as ASCII string of at most 10 digits} const CONNECT_TIMEOUT_MS_MAX: u128 = 9_999_999_999; pub struct RequestEnvelope { pub headers: HeaderMap, pub extensions: Extensions, pub timeout: Option, } pub struct ResponseDetails { pub status: StatusCode, pub headers: HeaderMap, pub extensions: Extensions, } impl ResponseDetails { pub fn from_http_response(response: http::Response) -> (Self, T) { let (parts, body) = response.into_parts(); ( Self { status: parts.status, headers: parts.headers, extensions: parts.extensions, }, body, ) } pub fn into_response(self, message: T) -> Result, Status> { let mut extensions = self.extensions; let metadata = crate::metadata::from_headers(self.headers, Some(&mut extensions)); Ok(crate::Response::from_parts(metadata, message, extensions)) } pub fn into_status(self, body: impl AsRef<[u8]>) -> Status { let mut status = ConnectStatus::from_body(body.as_ref()) .unwrap_or_else(|err| { tracing::warn!(?err, "failed to deserialize error response body"); None }) .and_then(|connect_status| { connect_status .to_status() .inspect_err(|err| { tracing::warn!(?err, "failed to construct error response details") }) .ok() }) .unwrap_or_else(|| Status::new(status_to_code(self.status), "")); *status.metadata_mut() = crate::metadata::from_headers(self.headers, None); status } }