Add EppRequest trait with related transact_new method

This commit is contained in:
Nicholas Rempel 2021-11-26 13:50:22 -08:00 committed by masalachai
parent 8de5984e38
commit 80c0040cd9
2 changed files with 65 additions and 4 deletions

View File

@ -55,8 +55,8 @@ use crate::error;
use crate::hello::{EppGreeting, EppHello};
use crate::login::{EppLogin, EppLoginResponse};
use crate::logout::{EppLogout, EppLogoutResponse};
use crate::request::generate_client_tr_id;
use crate::response::{EppCommandResponse, EppCommandResponseError};
use crate::request::{generate_client_tr_id, EppExtension, EppRequest};
use crate::response::{CommandResponseWithExtension, EppCommandResponse, EppCommandResponseError};
use crate::xml::EppXml;
/// Instances of the EppClient type are used to transact with the registry.
/// Once initialized, the EppClient instance can serialize EPP requests to XML and send them
@ -159,6 +159,22 @@ impl EppClient {
}
}
pub async fn transact_new<T, E>(
&mut self,
request: T,
id: &str,
) -> Result<CommandResponseWithExtension<<T as EppRequest<E>>::Output, E::Response>, error::Error>
where
T: EppRequest<E> + Debug,
E: EppExtension,
{
let epp_xml = request.serialize_request(id)?;
let response = self.connection.transact(&epp_xml).await?;
T::deserialize_response(&response)
}
/// Fetches the username used in the registry connection
pub fn username(&self) -> String {
self.credentials.0.to_string()

View File

@ -1,15 +1,60 @@
//! Types for EPP requests
use serde::{ser::SerializeStruct, ser::Serializer, Deserialize, Serialize};
use serde::{de::DeserializeOwned, ser::SerializeStruct, ser::Serializer, Deserialize, Serialize};
use std::error::Error;
use std::fmt::Debug;
use std::time::SystemTime;
use crate::common::{ElementName, EmptyTag, Extension, StringValue};
use crate::{
common::{ElementName, EmptyTag, EppObject, Extension, StringValue},
response::{CommandResponseStatus, CommandResponseWithExtension},
xml::EppXml,
};
use epp_client_macros::ElementName;
pub const EPP_VERSION: &str = "1.0";
pub const EPP_LANG: &str = "en";
/// Trait to set correct value for xml tags when tags are being generated from generic types
pub trait EppRequest<E: EppExtension>: Sized + Debug {
type Input: ElementName + DeserializeOwned + Serialize + Sized + Debug;
type Output: DeserializeOwned + Serialize + Debug;
fn into_parts(self) -> (Self::Input, Option<E>);
fn serialize_request(self, client_tr_id: &str) -> Result<String, Box<dyn std::error::Error>> {
let (command, extension) = self.into_parts();
let extension = extension.map(|data| Extension { data });
EppXml::serialize(&EppObject::build(CommandWithExtension {
command,
extension,
client_tr_id: client_tr_id.into(),
}))
}
fn deserialize_response(
epp_xml: &str,
) -> Result<CommandResponseWithExtension<Self::Output, E::Response>, crate::error::Error> {
let rsp =
<EppObject<CommandResponseWithExtension<Self::Output, E::Response>> as EppXml>::deserialize(
epp_xml,
)?;
match rsp.data.result.code {
0..=2000 => Ok(rsp.data),
_ => Err(crate::error::Error::EppCommandError(EppObject::build(
CommandResponseStatus {
result: rsp.data.result,
tr_ids: rsp.data.tr_ids,
},
))),
}
}
}
pub trait EppExtension: ElementName + DeserializeOwned + Serialize + Sized + Debug {
type Response: ElementName + DeserializeOwned + Serialize + Debug;
}
/// Type corresponding to the &lt;command&gt; tag in an EPP XML request
/// without an &lt;extension&gt; tag
pub type Command<T> = CommandWithExtension<T, EmptyTag>;