From 64532c3e4615cfd38acba7850514f8485ab93386 Mon Sep 17 00:00:00 2001 From: Dmitry Samoylov Date: Tue, 22 Mar 2022 21:22:58 +0700 Subject: [PATCH] Add `ClientBuilder::response_patcher()` To allow for patching responses from ONVIF devices that are not fully compliant with the spec. --- onvif/src/soap/client.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/onvif/src/soap/client.rs b/onvif/src/soap/client.rs index d26c4a4..bb2dbc1 100644 --- a/onvif/src/soap/client.rs +++ b/onvif/src/soap/client.rs @@ -9,6 +9,7 @@ use async_trait::async_trait; use schema::transport::{Error, Transport}; use std::{ fmt::{Debug, Formatter}, + sync::Arc, time::Duration, }; use url::Url; @@ -48,6 +49,7 @@ impl ClientBuilder { config: Config { uri: uri.clone(), credentials: None, + response_patcher: None, auth_type: AuthType::Any, timeout: Duration::from_secs(5), }, @@ -59,6 +61,11 @@ impl ClientBuilder { self } + pub fn response_patcher(mut self, response_patcher: Option) -> Self { + self.config.response_patcher = response_patcher; + self + } + pub fn auth_type(mut self, auth_type: AuthType) -> Self { self.config.auth_type = auth_type; self @@ -96,6 +103,7 @@ impl ClientBuilder { struct Config { uri: Url, credentials: Option, + response_patcher: Option, auth_type: AuthType, timeout: Duration, } @@ -122,6 +130,8 @@ impl Debug for Credentials { } } +pub type ResponsePatcher = Arc Result + Send + Sync>; + #[derive(Debug)] enum RequestAuthType { Digest(Digest), @@ -226,7 +236,19 @@ impl Client { .map_err(|e| Error::Protocol(e.to_string())) .and_then(|text| { debug!(self, "Response body: {}", text); - soap::unsoap(&text).map_err(|e| Error::Protocol(format!("{:?}", e))) + let response = + soap::unsoap(&text).map_err(|e| Error::Protocol(format!("{:?}", e)))?; + if let Some(response_patcher) = &self.config.response_patcher { + match response_patcher(&response) { + Ok(patched) => { + debug!(self, "Response (SOAP unwrapped, patched): {}", patched); + Ok(patched) + } + Err(e) => Err(Error::Protocol(format!("Patching failed: {e}"))), + } + } else { + Ok(response) + } }) } else if status == reqwest::StatusCode::UNAUTHORIZED { match auth_type {