From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id AC5FC1FF139 for ; Tue, 27 Jan 2026 13:27:04 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C82DF2169F; Tue, 27 Jan 2026 13:27:27 +0100 (CET) From: Christian Ebner To: pbs-devel@lists.proxmox.com Date: Tue, 27 Jan 2026 13:27:09 +0100 Message-ID: <20260127122712.505774-2-c.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260127122712.505774-1-c.ebner@proxmox.com> References: <20260127122712.505774-1-c.ebner@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1769516779988 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.047 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pbs-devel] [PATCH proxmox 1/3] s3-client: factor out optional response header parsing X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Backup Server development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pbs-devel-bounces@lists.proxmox.com Sender: "pbs-devel" Introduce an associated function to parse optional headers, currently only present for the date header. Further, reduce code duplication by using the same function also for the parsing of required headers. Will be used to parse optional headers set in the delete object response so they can be mapped to look like a delete objects response when adding a provider quirk to perform delete objects via individual delete object calls. Signed-off-by: Christian Ebner --- proxmox-s3-client/src/response_reader.rs | 47 +++++++++++++----------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/proxmox-s3-client/src/response_reader.rs b/proxmox-s3-client/src/response_reader.rs index e03b3bb0..7066c33b 100644 --- a/proxmox-s3-client/src/response_reader.rs +++ b/proxmox-s3-client/src/response_reader.rs @@ -251,7 +251,7 @@ impl ResponseReader { let body = String::from_utf8(body.to_vec())?; - let date = Self::parse_optional_date_header(&parts.headers)?; + let date = Self::parse_optional_header(header::DATE, &parts.headers)?; let response: ListObjectsV2ResponseBody = serde_xml_rs::from_str(&body).context("failed to parse response body")?; @@ -282,7 +282,7 @@ impl ResponseReader { let content_length: u64 = Self::parse_header(header::CONTENT_LENGTH, &parts.headers)?; let content_type = Self::parse_header(header::CONTENT_TYPE, &parts.headers)?; let e_tag = Self::parse_header(header::ETAG, &parts.headers)?; - let date = Self::parse_optional_date_header(&parts.headers)?; + let date = Self::parse_optional_header(header::DATE, &parts.headers)?; let last_modified = Self::parse_header(header::LAST_MODIFIED, &parts.headers)?; Ok(Some(HeadObjectResponse { @@ -314,7 +314,7 @@ impl ResponseReader { let content_length: u64 = Self::parse_header(header::CONTENT_LENGTH, &parts.headers)?; let content_type = Self::parse_header(header::CONTENT_TYPE, &parts.headers)?; let e_tag = Self::parse_header(header::ETAG, &parts.headers)?; - let date = Self::parse_optional_date_header(&parts.headers)?; + let date = Self::parse_optional_header(header::DATE, &parts.headers)?; let last_modified = Self::parse_header(header::LAST_MODIFIED, &parts.headers)?; Ok(Some(GetObjectResponse { @@ -477,30 +477,30 @@ impl ResponseReader { ::Err: Send + Sync + 'static, Result::Err>: Context::Err>, { - let header_value = headers - .get(&name) + let value = Self::parse_optional_header(name.clone(), headers)? .ok_or_else(|| anyhow!("missing header '{name}'"))?; - let header_str = header_value - .to_str() - .with_context(|| format!("non UTF-8 header '{name}'"))?; - let value = header_str - .parse() - .with_context(|| format!("failed to parse header '{name}'"))?; Ok(value) } - fn parse_optional_date_header(headers: &HeaderMap) -> Result, Error> { - let header_value = match headers.get(header::DATE) { + fn parse_optional_header( + name: HeaderName, + headers: &HeaderMap, + ) -> Result, Error> + where + ::Err: Send + Sync + 'static, + Result::Err>: Context::Err>, + { + let header_value = match headers.get(&name) { Some(value) => value, None => return Ok(None), }; let header_str = header_value .to_str() - .with_context(|| format!("non UTF-8 header '{}'", header::DATE))?; - let date: HttpDate = header_str + .with_context(|| format!("non UTF-8 header '{name}'"))?; + let value = header_str .parse() - .with_context(|| format!("failed to parse header '{}'", header::DATE))?; - Ok(Some(date)) + .with_context(|| format!("failed to parse header '{name}'"))?; + Ok(Some(value)) } } @@ -615,7 +615,8 @@ fn test_optional_date_header_parsing() { let expected_date = "Wed, 12 Oct 2009 17:50:00 GMT"; header_map.insert(header::DATE, expected_date.parse().unwrap()); - let parsed_date = ResponseReader::parse_optional_date_header(&header_map).unwrap(); + let parsed_date: Option = + ResponseReader::parse_optional_header(header::DATE, &header_map).unwrap(); assert!(parsed_date.is_some()); assert_eq!( parsed_date.unwrap(), @@ -625,10 +626,12 @@ fn test_optional_date_header_parsing() { header_map.clear(); let invalid_date_format = "2019-11-10"; header_map.insert(header::DATE, invalid_date_format.parse().unwrap()); - assert!(ResponseReader::parse_optional_date_header(&header_map).is_err()); + assert!(ResponseReader::parse_optional_header::(header::DATE, &header_map).is_err()); header_map.clear(); - assert!(ResponseReader::parse_optional_date_header(&header_map) - .unwrap() - .is_none()); + assert!( + ResponseReader::parse_optional_header::(header::DATE, &header_map) + .unwrap() + .is_none() + ); } -- 2.47.3 _______________________________________________ pbs-devel mailing list pbs-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel