Use different type wrappers instead of single EppObject
This commit is contained in:
parent
57d60807d8
commit
ce30f1599f
|
@ -45,10 +45,9 @@
|
||||||
|
|
||||||
use std::{error::Error, fmt::Debug};
|
use std::{error::Error, fmt::Debug};
|
||||||
|
|
||||||
use crate::common::EppObject;
|
|
||||||
use crate::config::EppClientConfig;
|
use crate::config::EppClientConfig;
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::hello::{Greeting, Hello};
|
use crate::hello::{Greeting, GreetingDocument, HelloDocument};
|
||||||
use crate::registry::{epp_connect, EppConnection};
|
use crate::registry::{epp_connect, EppConnection};
|
||||||
use crate::request::{EppExtension, EppRequest};
|
use crate::request::{EppExtension, EppRequest};
|
||||||
use crate::response::Response;
|
use crate::response::Response;
|
||||||
|
@ -81,11 +80,11 @@ impl EppClient {
|
||||||
|
|
||||||
/// Executes an EPP Hello call and returns the response as an `Greeting`
|
/// Executes an EPP Hello call and returns the response as an `Greeting`
|
||||||
pub async fn hello(&mut self) -> Result<Greeting, Box<dyn Error>> {
|
pub async fn hello(&mut self) -> Result<Greeting, Box<dyn Error>> {
|
||||||
let hello_xml = EppObject::<Hello>::build(Hello).serialize()?;
|
let hello_xml = HelloDocument::default().serialize()?;
|
||||||
|
|
||||||
let response = self.connection.transact(&hello_xml).await?;
|
let response = self.connection.transact(&hello_xml).await?;
|
||||||
|
|
||||||
Ok(EppObject::<Greeting>::deserialize(&response)?.data)
|
Ok(GreetingDocument::deserialize(&response)?.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn transact<T, E>(
|
pub async fn transact<T, E>(
|
||||||
|
@ -117,6 +116,6 @@ impl EppClient {
|
||||||
|
|
||||||
/// Returns the greeting received on establishment of the connection as an `Greeting`
|
/// Returns the greeting received on establishment of the connection as an `Greeting`
|
||||||
pub fn greeting(&self) -> Result<Greeting, error::Error> {
|
pub fn greeting(&self) -> Result<Greeting, error::Error> {
|
||||||
EppObject::<Greeting>::deserialize(&self.connection.greeting).map(|obj| obj.data)
|
GreetingDocument::deserialize(&self.connection.greeting).map(|obj| obj.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
use std::{fmt::Display, str::FromStr};
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
use epp_client_macros::ElementName;
|
use epp_client_macros::ElementName;
|
||||||
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::request::EppExtension;
|
use crate::request::EppExtension;
|
||||||
|
|
||||||
const EPP_XMLNS: &str = "urn:ietf:params:xml:ns:epp-1.0";
|
pub(crate) const EPP_XMLNS: &str = "urn:ietf:params:xml:ns:epp-1.0";
|
||||||
|
|
||||||
/// Wraps String for easier serialization to and from values that are inner text
|
/// Wraps String for easier serialization to and from values that are inner text
|
||||||
/// for tags rather than attributes
|
/// for tags rather than attributes
|
||||||
|
@ -46,33 +46,6 @@ impl EppExtension for NoExtension {
|
||||||
type Response = NoExtension;
|
type Response = NoExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An EPP XML Document that is used either as an EPP XML request or
|
|
||||||
/// an EPP XML response
|
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
|
||||||
#[serde(rename = "epp")]
|
|
||||||
pub struct EppObject<T: ElementName> {
|
|
||||||
/// XML namespace for the <epp> tag
|
|
||||||
pub xmlns: String,
|
|
||||||
/// the request or response object that is set or received in the EPP XML document
|
|
||||||
#[serde(alias = "greeting", alias = "response")]
|
|
||||||
pub data: T,
|
|
||||||
// TODO: save serialized xml in the instance for debugging or client logging purposes
|
|
||||||
// #[serde(skip)]
|
|
||||||
// pub xml: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ElementName + Serialize> Serialize for EppObject<T> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let mut state = serializer.serialize_struct("epp", 4)?;
|
|
||||||
state.serialize_field("xmlns", &self.xmlns)?;
|
|
||||||
state.serialize_field(T::ELEMENT, &self.data)?;
|
|
||||||
state.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The <option> type in EPP XML login requests
|
/// The <option> type in EPP XML login requests
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||||
#[serde(rename = "options")]
|
#[serde(rename = "options")]
|
||||||
|
@ -93,26 +66,6 @@ impl Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type representing the <extension> tag for an EPP document
|
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
|
||||||
#[serde(rename = "extension")]
|
|
||||||
pub struct Extension<E: ElementName> {
|
|
||||||
/// Data under the <extension> tag
|
|
||||||
#[serde(alias = "upData", alias = "namestoreExt", alias = "infData")]
|
|
||||||
pub data: E,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: ElementName + Serialize> Serialize for Extension<E> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let mut state = serializer.serialize_struct("extension", 1)?;
|
|
||||||
state.serialize_field(E::ELEMENT, &self.data)?;
|
|
||||||
state.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The <svcExtension> type in EPP XML
|
/// The <svcExtension> type in EPP XML
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||||
#[serde(rename = "svcExtension")]
|
#[serde(rename = "svcExtension")]
|
||||||
|
@ -133,17 +86,6 @@ pub struct Services {
|
||||||
pub svc_ext: Option<ServiceExtension>,
|
pub svc_ext: Option<ServiceExtension>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ElementName> EppObject<T> {
|
|
||||||
/// Create the enclosing EPP XML tag <epp> for data that represents an EPP XML request or response
|
|
||||||
pub fn build(data: T) -> EppObject<T> {
|
|
||||||
EppObject {
|
|
||||||
// xml: None,
|
|
||||||
data,
|
|
||||||
xmlns: EPP_XMLNS.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The <status> attribute on EPP XML for domain transactions
|
/// The <status> attribute on EPP XML for domain transactions
|
||||||
pub type DomainStatus = ContactStatus;
|
pub type DomainStatus = ContactStatus;
|
||||||
/// The <status> attribute on EPP XML for host transactions
|
/// The <status> attribute on EPP XML for host transactions
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use chrono::FixedOffset;
|
use chrono::FixedOffset;
|
||||||
use epp_client_macros::ElementName;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{ElementName, NoExtension, StringValue},
|
common::{NoExtension, StringValue},
|
||||||
request::EppExtension,
|
request::EppExtension,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,7 +63,6 @@ impl fmt::Display for GMonthDay {
|
||||||
/// use epp_client::config::{EppClientConfig, RegistryConfig};
|
/// use epp_client::config::{EppClientConfig, RegistryConfig};
|
||||||
/// use epp_client::EppClient;
|
/// use epp_client::EppClient;
|
||||||
/// use epp_client::common::{DomainStatus, DomainContact};
|
/// use epp_client::common::{DomainStatus, DomainContact};
|
||||||
/// use epp_client::extensions::consolidate::Sync;
|
|
||||||
/// use epp_client::domain::update::DomainUpdate;
|
/// use epp_client::domain::update::DomainUpdate;
|
||||||
/// use epp_client::extensions::consolidate;
|
/// use epp_client::extensions::consolidate;
|
||||||
/// use epp_client::extensions::consolidate::GMonthDay;
|
/// use epp_client::extensions::consolidate::GMonthDay;
|
||||||
|
@ -98,10 +96,10 @@ impl fmt::Display for GMonthDay {
|
||||||
/// client.transact(login, "transaction-id").await.unwrap();
|
/// client.transact(login, "transaction-id").await.unwrap();
|
||||||
///
|
///
|
||||||
/// let exp = GMonthDay::new(5, 31, None).unwrap();
|
/// let exp = GMonthDay::new(5, 31, None).unwrap();
|
||||||
/// let consolidate_ext = consolidate::Sync::new(exp);
|
/// let consolidate_ext = consolidate::Update::new(exp);
|
||||||
///
|
///
|
||||||
/// // Create an DomainUpdate instance
|
/// // Create an DomainUpdate instance
|
||||||
/// let mut domain_update = DomainUpdate::<consolidate::Sync>::new("eppdev-100.com").with_extension(consolidate_ext);
|
/// let mut domain_update = DomainUpdate::<consolidate::Update>::new("eppdev-100.com").with_extension(consolidate_ext);
|
||||||
///
|
///
|
||||||
/// // send it to the registry and receive a response of type EppDomainUpdateResponse
|
/// // send it to the registry and receive a response of type EppDomainUpdateResponse
|
||||||
/// let response = client.transact(domain_update, "transaction-id").await.unwrap();
|
/// let response = client.transact(domain_update, "transaction-id").await.unwrap();
|
||||||
|
@ -112,24 +110,32 @@ impl fmt::Display for GMonthDay {
|
||||||
/// client.transact(logout, "transaction-id").await.unwrap();
|
/// client.transact(logout, "transaction-id").await.unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
impl Sync {
|
impl Update {
|
||||||
/// Create a new RGP restore report request
|
/// Create a new RGP restore report request
|
||||||
pub fn new(expiration: GMonthDay) -> Sync {
|
pub fn new(expiration: GMonthDay) -> Self {
|
||||||
Sync {
|
Self {
|
||||||
|
data: UpdateData {
|
||||||
xmlns: XMLNS.to_string(),
|
xmlns: XMLNS.to_string(),
|
||||||
exp: expiration.to_string().into(),
|
exp: expiration.to_string().into(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EppExtension for Sync {
|
impl EppExtension for Update {
|
||||||
type Response = NoExtension;
|
type Response = NoExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, ElementName)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[element_name(name = "sync:update")]
|
#[serde(rename = "extension")]
|
||||||
|
pub struct Update {
|
||||||
|
#[serde(rename = "sync:update")]
|
||||||
|
pub data: UpdateData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
/// Type for EPP XML <consolidate> extension
|
/// Type for EPP XML <consolidate> extension
|
||||||
pub struct Sync {
|
pub struct UpdateData {
|
||||||
/// XML namespace for the consolidate extension
|
/// XML namespace for the consolidate extension
|
||||||
#[serde(rename = "xmlns:sync", alias = "xmlns")]
|
#[serde(rename = "xmlns:sync", alias = "xmlns")]
|
||||||
pub xmlns: String,
|
pub xmlns: String,
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
//! Types for EPP namestore request and responses
|
//! Types for EPP namestore request and responses
|
||||||
|
|
||||||
use epp_client_macros::ElementName;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{common::StringValue, request::EppExtension};
|
||||||
common::{ElementName, StringValue},
|
|
||||||
request::EppExtension,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const XMLNS: &str = "http://www.verisign-grs.com/epp/namestoreExt-1.1";
|
pub const XMLNS: &str = "http://www.verisign-grs.com/epp/namestoreExt-1.1";
|
||||||
|
|
||||||
|
@ -68,8 +64,10 @@ impl NameStore {
|
||||||
/// Create a new RGP restore report request
|
/// Create a new RGP restore report request
|
||||||
pub fn new(subproduct: &str) -> NameStore {
|
pub fn new(subproduct: &str) -> NameStore {
|
||||||
NameStore {
|
NameStore {
|
||||||
|
data: NameStoreData {
|
||||||
xmlns: XMLNS.to_string(),
|
xmlns: XMLNS.to_string(),
|
||||||
subproduct: subproduct.into(),
|
subproduct: subproduct.into(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,10 +76,16 @@ impl EppExtension for NameStore {
|
||||||
type Response = NameStore;
|
type Response = NameStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, ElementName)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[element_name(name = "namestoreExt:namestoreExt")]
|
#[serde(rename = "namestoreExt:namestoreExt")]
|
||||||
/// Type for EPP XML <namestoreExt> extension
|
|
||||||
pub struct NameStore {
|
pub struct NameStore {
|
||||||
|
#[serde(rename = "namestoreExt:namestoreExt", alias = "namestoreExt")]
|
||||||
|
pub data: NameStoreData,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
/// Type for EPP XML <namestoreExt> extension
|
||||||
|
pub struct NameStoreData {
|
||||||
/// XML namespace for the RGP restore extension
|
/// XML namespace for the RGP restore extension
|
||||||
#[serde(rename = "xmlns:namestoreExt", alias = "xmlns")]
|
#[serde(rename = "xmlns:namestoreExt", alias = "xmlns")]
|
||||||
pub xmlns: String,
|
pub xmlns: String,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::request::EppExtension;
|
||||||
use chrono::{DateTime, SecondsFormat, Utc};
|
use chrono::{DateTime, SecondsFormat, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::XMLNS;
|
use super::{Update, XMLNS};
|
||||||
|
|
||||||
/// Type that represents the domain rgp restore report extension
|
/// Type that represents the domain rgp restore report extension
|
||||||
///
|
///
|
||||||
|
@ -19,7 +19,7 @@ use super::XMLNS;
|
||||||
/// use epp_client::config::{EppClientConfig, RegistryConfig};
|
/// use epp_client::config::{EppClientConfig, RegistryConfig};
|
||||||
/// use epp_client::EppClient;
|
/// use epp_client::EppClient;
|
||||||
/// use epp_client::common::{DomainStatus, DomainContact};
|
/// use epp_client::common::{DomainStatus, DomainContact};
|
||||||
/// use epp_client::extensions::rgp::report::RgpRestoreReport;
|
/// use epp_client::extensions::rgp::{Update, report::RgpRestoreReport};
|
||||||
/// use epp_client::domain::update::DomainUpdate;
|
/// use epp_client::domain::update::DomainUpdate;
|
||||||
/// use epp_client::common::NoExtension;
|
/// use epp_client::common::NoExtension;
|
||||||
/// use epp_client::login::Login;
|
/// use epp_client::login::Login;
|
||||||
|
@ -63,7 +63,7 @@ use super::XMLNS;
|
||||||
/// ];
|
/// ];
|
||||||
/// let other = "Supporting information goes here.";
|
/// let other = "Supporting information goes here.";
|
||||||
///
|
///
|
||||||
/// let domain_restore_report = RgpRestoreReport::new(
|
/// let domain_restore_report = Update { data: RgpRestoreReport::new(
|
||||||
/// pre_data,
|
/// pre_data,
|
||||||
/// post_data,
|
/// post_data,
|
||||||
/// deleted_at,
|
/// deleted_at,
|
||||||
|
@ -71,10 +71,10 @@ use super::XMLNS;
|
||||||
/// restore_reason,
|
/// restore_reason,
|
||||||
/// &statements,
|
/// &statements,
|
||||||
/// other
|
/// other
|
||||||
/// );
|
/// ) };
|
||||||
///
|
///
|
||||||
/// // Create an DomainUpdate instance
|
/// // Create an DomainUpdate instance
|
||||||
/// let mut domain_update = DomainUpdate::<RgpRestoreReport>::new("eppdev-100.com").with_extension(domain_restore_report);
|
/// let mut domain_update = DomainUpdate::<Update<RgpRestoreReport>>::new("eppdev-100.com").with_extension(domain_restore_report);
|
||||||
///
|
///
|
||||||
/// // send it to the registry and receive a response of type EppDomainUpdateResponse
|
/// // send it to the registry and receive a response of type EppDomainUpdateResponse
|
||||||
/// let response = client.transact(domain_update, "transaction-id").await.unwrap();
|
/// let response = client.transact(domain_update, "transaction-id").await.unwrap();
|
||||||
|
@ -120,7 +120,7 @@ impl RgpRestoreReport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EppExtension for RgpRestoreReport {
|
impl EppExtension for Update<RgpRestoreReport> {
|
||||||
type Response = NoExtension;
|
type Response = NoExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::request::EppExtension;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::XMLNS;
|
use super::{Update, XMLNS};
|
||||||
|
|
||||||
/// Type that represents the <epp> request for a domain rgp restore request command
|
/// Type that represents the <epp> request for a domain rgp restore request command
|
||||||
///
|
///
|
||||||
|
@ -19,7 +19,7 @@ use super::XMLNS;
|
||||||
///
|
///
|
||||||
/// use epp_client::config::{EppClientConfig, RegistryConfig};
|
/// use epp_client::config::{EppClientConfig, RegistryConfig};
|
||||||
/// use epp_client::EppClient;
|
/// use epp_client::EppClient;
|
||||||
/// use epp_client::extensions::rgp::request::RgpRestoreRequest;
|
/// use epp_client::extensions::rgp::{Update, request::RgpRestoreRequest};
|
||||||
/// use epp_client::domain::update::DomainUpdate;
|
/// use epp_client::domain::update::DomainUpdate;
|
||||||
/// use epp_client::login::Login;
|
/// use epp_client::login::Login;
|
||||||
/// use epp_client::logout::Logout;
|
/// use epp_client::logout::Logout;
|
||||||
|
@ -49,10 +49,10 @@ use super::XMLNS;
|
||||||
/// client.transact(login, "transaction-id").await.unwrap();
|
/// client.transact(login, "transaction-id").await.unwrap();
|
||||||
///
|
///
|
||||||
/// // Create an RgpRestoreRequest instance
|
/// // Create an RgpRestoreRequest instance
|
||||||
/// let domain_restore_req = RgpRestoreRequest::new();
|
/// let domain_restore_req = Update { data: RgpRestoreRequest::default() };
|
||||||
///
|
///
|
||||||
/// // Create an DomainUpdate instance
|
/// // Create an DomainUpdate instance
|
||||||
/// let mut domain_update = DomainUpdate::<RgpRestoreRequest>::new("eppdev-100.com").with_extension(domain_restore_req);
|
/// let mut domain_update = DomainUpdate::<Update<RgpRestoreRequest>>::new("eppdev-100.com").with_extension(domain_restore_req);
|
||||||
///
|
///
|
||||||
/// // send it to the registry and receive a response of type EppDomainUpdateResponse
|
/// // send it to the registry and receive a response of type EppDomainUpdateResponse
|
||||||
/// let response = client.transact(domain_update, "transaction-id").await.unwrap();
|
/// let response = client.transact(domain_update, "transaction-id").await.unwrap();
|
||||||
|
@ -63,26 +63,9 @@ use super::XMLNS;
|
||||||
/// client.transact(logout, "transaction-id").await.unwrap();
|
/// client.transact(logout, "transaction-id").await.unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
impl RgpRestoreRequest {
|
|
||||||
/// Creates a new instance of EppDomainRgpRestoreRequest
|
|
||||||
pub fn new() -> RgpRestoreRequest {
|
|
||||||
RgpRestoreRequest {
|
|
||||||
xmlns: XMLNS.to_string(),
|
|
||||||
restore: RgpRestoreRequestData {
|
|
||||||
op: "request".to_string(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for RgpRestoreRequest {
|
impl EppExtension for Update<RgpRestoreRequest> {
|
||||||
fn default() -> Self {
|
type Response = Update<RgpRequestResponse>;
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EppExtension for RgpRestoreRequest {
|
|
||||||
type Response = RgpRequestResponse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
|
@ -106,6 +89,17 @@ pub struct RgpRestoreRequest {
|
||||||
restore: RgpRestoreRequestData,
|
restore: RgpRestoreRequestData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for RgpRestoreRequest {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
xmlns: XMLNS.to_string(),
|
||||||
|
restore: RgpRestoreRequestData {
|
||||||
|
op: "request".to_string(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
|
|
||||||
/// Type that represents the <rgpStatus> tag for domain rgp restore request response
|
/// Type that represents the <rgpStatus> tag for domain rgp restore request response
|
||||||
|
|
|
@ -3,14 +3,31 @@ use std::fmt::Debug;
|
||||||
use epp_client_macros::ElementName;
|
use epp_client_macros::ElementName;
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
|
||||||
use crate::common::{ElementName, Options, ServiceExtension, Services, StringValue};
|
use crate::common::{ElementName, Options, ServiceExtension, Services, StringValue, EPP_XMLNS};
|
||||||
|
use crate::xml::EppXml;
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, ElementName)]
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
#[element_name(name = "hello")]
|
struct Hello;
|
||||||
/// Type corresponding to the <hello> tag in an EPP XML hello request
|
|
||||||
pub struct Hello;
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
#[serde(rename = "epp")]
|
||||||
|
pub struct HelloDocument {
|
||||||
|
xmlns: &'static str,
|
||||||
|
hello: Hello,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HelloDocument {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
xmlns: EPP_XMLNS,
|
||||||
|
hello: Hello,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EppXml for HelloDocument {}
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
|
|
||||||
|
@ -278,3 +295,12 @@ pub struct Greeting {
|
||||||
/// Data under the <dcp> element
|
/// Data under the <dcp> element
|
||||||
pub dcp: Dcp,
|
pub dcp: Dcp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||||
|
#[serde(rename = "epp")]
|
||||||
|
pub struct GreetingDocument {
|
||||||
|
#[serde(rename = "greeting")]
|
||||||
|
pub data: Greeting,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EppXml for GreetingDocument {}
|
||||||
|
|
|
@ -136,10 +136,23 @@ pub mod extensions {
|
||||||
pub mod consolidate;
|
pub mod consolidate;
|
||||||
pub mod namestore;
|
pub mod namestore;
|
||||||
pub mod rgp {
|
pub mod rgp {
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod report;
|
pub mod report;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
|
|
||||||
pub const XMLNS: &str = "urn:ietf:params:xml:ns:rgp-1.0";
|
pub const XMLNS: &str = "urn:ietf:params:xml:ns:rgp-1.0";
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Update<T> {
|
||||||
|
#[serde(
|
||||||
|
rename = "rgp:update",
|
||||||
|
alias = "update",
|
||||||
|
alias = "upData",
|
||||||
|
alias = "infData"
|
||||||
|
)]
|
||||||
|
pub data: T,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ use serde::{de::DeserializeOwned, ser::SerializeStruct, ser::Serializer, Deseria
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{ElementName, EppObject, Extension, StringValue},
|
common::{ElementName, StringValue, EPP_XMLNS},
|
||||||
response::{Response, ResponseStatus},
|
response::{Response, ResponseDocument, ResponseStatus},
|
||||||
xml::EppXml,
|
xml::EppXml,
|
||||||
};
|
};
|
||||||
use epp_client_macros::ElementName;
|
use epp_client_macros::ElementName;
|
||||||
|
@ -15,16 +15,16 @@ pub const EPP_LANG: &str = "en";
|
||||||
|
|
||||||
/// Trait to set correct value for xml tags when tags are being generated from generic types
|
/// Trait to set correct value for xml tags when tags are being generated from generic types
|
||||||
pub trait EppRequest<E: EppExtension>: Sized + Debug {
|
pub trait EppRequest<E: EppExtension>: Sized + Debug {
|
||||||
type Input: ElementName + DeserializeOwned + Serialize + Sized + Debug;
|
type Input: ElementName + Serialize + Sized + Debug;
|
||||||
type Output: DeserializeOwned + Serialize + Debug;
|
type Output: DeserializeOwned + Debug;
|
||||||
|
|
||||||
fn into_parts(self) -> (Self::Input, Option<E>);
|
fn into_parts(self) -> (Self::Input, Option<E>);
|
||||||
|
|
||||||
fn serialize_request(self, client_tr_id: &str) -> Result<String, Box<dyn std::error::Error>> {
|
fn serialize_request(self, client_tr_id: &str) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
let (command, extension) = self.into_parts();
|
let (command, extension) = self.into_parts();
|
||||||
let extension = extension.map(|data| Extension { data });
|
<CommandDocument<Self::Input, E> as EppXml>::serialize(&CommandDocument::new(Command {
|
||||||
EppXml::serialize(&EppObject::build(Command {
|
command: <Self::Input as ElementName>::ELEMENT,
|
||||||
command,
|
data: command,
|
||||||
extension,
|
extension,
|
||||||
client_tr_id: client_tr_id.into(),
|
client_tr_id: client_tr_id.into(),
|
||||||
}))
|
}))
|
||||||
|
@ -33,7 +33,7 @@ pub trait EppRequest<E: EppExtension>: Sized + Debug {
|
||||||
fn deserialize_response(
|
fn deserialize_response(
|
||||||
epp_xml: &str,
|
epp_xml: &str,
|
||||||
) -> Result<Response<Self::Output, E::Response>, crate::error::Error> {
|
) -> Result<Response<Self::Output, E::Response>, crate::error::Error> {
|
||||||
let rsp = <EppObject<Response<Self::Output, E::Response>> as EppXml>::deserialize(epp_xml)?;
|
let rsp = <ResponseDocument<Self::Output, E::Response> as EppXml>::deserialize(epp_xml)?;
|
||||||
match rsp.data.result.code {
|
match rsp.data.result.code {
|
||||||
0..=2000 => Ok(rsp.data),
|
0..=2000 => Ok(rsp.data),
|
||||||
_ => Err(crate::error::Error::EppCommandError(ResponseStatus {
|
_ => Err(crate::error::Error::EppCommandError(ResponseStatus {
|
||||||
|
@ -44,44 +44,52 @@ pub trait EppRequest<E: EppExtension>: Sized + Debug {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EppExtension: ElementName + DeserializeOwned + Serialize + Sized + Debug {
|
pub trait EppExtension: Serialize + Sized + Debug {
|
||||||
type Response: ElementName + DeserializeOwned + Serialize + Debug;
|
type Response: DeserializeOwned + Debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, PartialEq, ElementName)]
|
#[derive(Deserialize, Debug, PartialEq, ElementName)]
|
||||||
#[element_name(name = "command")]
|
#[element_name(name = "command")]
|
||||||
/// Type corresponding to the <command> tag in an EPP XML request
|
/// Type corresponding to the <command> tag in an EPP XML request
|
||||||
/// with an <extension> tag
|
/// with an <extension> tag
|
||||||
pub struct Command<T: ElementName, E: ElementName> {
|
pub struct Command<D, E> {
|
||||||
|
pub command: &'static str,
|
||||||
/// The instance that will be used to populate the <command> tag
|
/// The instance that will be used to populate the <command> tag
|
||||||
pub command: T,
|
pub data: D,
|
||||||
/// The client TRID
|
/// The client TRID
|
||||||
pub extension: Option<Extension<E>>,
|
pub extension: Option<E>,
|
||||||
#[serde(rename = "clTRID")]
|
#[serde(rename = "clTRID")]
|
||||||
pub client_tr_id: StringValue,
|
pub client_tr_id: StringValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ElementName + Serialize, E: ElementName + Serialize> Serialize for Command<T, E> {
|
impl<D: Serialize, E: Serialize> Serialize for Command<D, E> {
|
||||||
/// Serializes the generic type T to the proper XML tag (set by the `#[element_name(name = <tagname>)]` attribute) for the request
|
/// Serializes the generic type T to the proper XML tag (set by the `#[element_name(name = <tagname>)]` attribute) for the request
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
let mut state = serializer.serialize_struct("command", 3)?;
|
let mut state = serializer.serialize_struct("command", 3)?;
|
||||||
state.serialize_field(T::ELEMENT, &self.command)?;
|
state.serialize_field(self.command, &self.data)?;
|
||||||
state.serialize_field("extension", &self.extension)?;
|
state.serialize_field("extension", &self.extension)?;
|
||||||
state.serialize_field("clTRID", &self.client_tr_id)?;
|
state.serialize_field("clTRID", &self.client_tr_id)?;
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ElementName, E: ElementName> Command<T, E> {
|
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||||
/// Creates a new <command> tag for an EPP document with a containing <extension> tag
|
#[serde(rename = "epp")]
|
||||||
pub fn build(command: T, ext: E, client_tr_id: &str) -> Command<T, E> {
|
pub struct CommandDocument<D, E> {
|
||||||
Command {
|
xmlns: &'static str,
|
||||||
|
command: Command<D, E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, E> CommandDocument<D, E> {
|
||||||
|
pub fn new(command: Command<D, E>) -> Self {
|
||||||
|
Self {
|
||||||
|
xmlns: EPP_XMLNS,
|
||||||
command,
|
command,
|
||||||
extension: Some(Extension { data: ext }),
|
|
||||||
client_tr_id: client_tr_id.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<D: Serialize, E: Serialize> EppXml for CommandDocument<D, E> {}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//! Types for EPP responses
|
//! Types for EPP responses
|
||||||
|
|
||||||
use epp_client_macros::*;
|
use epp_client_macros::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::common::{ElementName, Extension, StringValue};
|
use crate::common::{ElementName, StringValue};
|
||||||
|
use crate::xml::EppXml;
|
||||||
|
|
||||||
/// Type corresponding to the <undef> tag an EPP response XML
|
/// Type corresponding to the <undef> tag an EPP response XML
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||||
|
@ -70,10 +71,9 @@ pub struct MessageQueue {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, ElementName)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, ElementName)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
#[element_name(name = "response")]
|
|
||||||
/// Type corresponding to the <response> tag in an EPP response XML
|
/// Type corresponding to the <response> tag in an EPP response XML
|
||||||
/// containing an <extension> tag
|
/// containing an <extension> tag
|
||||||
pub struct Response<T, E: ElementName> {
|
pub struct Response<D, E> {
|
||||||
/// Data under the <result> tag
|
/// Data under the <result> tag
|
||||||
pub result: EppResult,
|
pub result: EppResult,
|
||||||
/// Data under the <msgQ> tag
|
/// Data under the <msgQ> tag
|
||||||
|
@ -81,14 +81,32 @@ pub struct Response<T, E: ElementName> {
|
||||||
pub message_queue: Option<MessageQueue>,
|
pub message_queue: Option<MessageQueue>,
|
||||||
#[serde(rename = "resData")]
|
#[serde(rename = "resData")]
|
||||||
/// Data under the <resData> tag
|
/// Data under the <resData> tag
|
||||||
pub res_data: Option<T>,
|
pub res_data: Option<D>,
|
||||||
/// Data under the <extension> tag
|
/// Data under the <extension> tag
|
||||||
pub extension: Option<Extension<E>>,
|
pub extension: Option<E>,
|
||||||
/// Data under the <trID> tag
|
/// Data under the <trID> tag
|
||||||
#[serde(rename = "trID")]
|
#[serde(rename = "trID")]
|
||||||
pub tr_ids: ResponseTRID,
|
pub tr_ids: ResponseTRID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
|
#[serde(rename = "epp")]
|
||||||
|
pub struct ResponseDocument<D, E> {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub data: Response<D, E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: DeserializeOwned, E: DeserializeOwned> EppXml for ResponseDocument<D, E> {}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
|
#[serde(rename = "epp")]
|
||||||
|
pub struct ResultDocument {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub data: ResponseStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EppXml for ResultDocument {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, ElementName)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, ElementName)]
|
||||||
#[element_name(name = "response")]
|
#[element_name(name = "response")]
|
||||||
/// Type corresponding to the <response> tag in an EPP response XML
|
/// Type corresponding to the <response> tag in an EPP response XML
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
mod response {
|
mod response {
|
||||||
use super::super::get_xml;
|
use super::super::get_xml;
|
||||||
use super::super::CLTRID;
|
use super::super::CLTRID;
|
||||||
use crate::common::{EppObject, NoExtension};
|
use crate::common::NoExtension;
|
||||||
use crate::contact::check::ContactCheck;
|
use crate::contact::check::ContactCheck;
|
||||||
use crate::contact::create::ContactCreate;
|
use crate::contact::create::ContactCreate;
|
||||||
use crate::contact::delete::ContactDelete;
|
use crate::contact::delete::ContactDelete;
|
||||||
|
@ -21,9 +21,9 @@ mod response {
|
||||||
use crate::domain::transfer::DomainTransferRequest;
|
use crate::domain::transfer::DomainTransferRequest;
|
||||||
use crate::domain::update::DomainUpdate;
|
use crate::domain::update::DomainUpdate;
|
||||||
use crate::extensions::namestore::NameStore;
|
use crate::extensions::namestore::NameStore;
|
||||||
use crate::extensions::rgp::request::RgpRestoreRequest;
|
use crate::extensions::rgp;
|
||||||
use crate::hello::ExpiryType;
|
use crate::hello::ExpiryType;
|
||||||
use crate::hello::Greeting;
|
use crate::hello::GreetingDocument;
|
||||||
use crate::hello::Relative;
|
use crate::hello::Relative;
|
||||||
use crate::host::check::HostCheck;
|
use crate::host::check::HostCheck;
|
||||||
use crate::host::create::HostCreate;
|
use crate::host::create::HostCreate;
|
||||||
|
@ -35,7 +35,7 @@ mod response {
|
||||||
use crate::message::ack::MessageAck;
|
use crate::message::ack::MessageAck;
|
||||||
use crate::message::poll::MessagePoll;
|
use crate::message::poll::MessagePoll;
|
||||||
use crate::request::EppRequest;
|
use crate::request::EppRequest;
|
||||||
use crate::response::ResponseStatus;
|
use crate::response::ResultDocument;
|
||||||
use crate::xml::EppXml;
|
use crate::xml::EppXml;
|
||||||
|
|
||||||
const SVTRID: &str = "RO-6879-1627224678242975";
|
const SVTRID: &str = "RO-6879-1627224678242975";
|
||||||
|
@ -44,7 +44,7 @@ mod response {
|
||||||
#[test]
|
#[test]
|
||||||
fn greeting() {
|
fn greeting() {
|
||||||
let xml = get_xml("response/greeting.xml").unwrap();
|
let xml = get_xml("response/greeting.xml").unwrap();
|
||||||
let object = EppObject::<Greeting>::deserialize(xml.as_str()).unwrap();
|
let object = GreetingDocument::deserialize(xml.as_str()).unwrap();
|
||||||
|
|
||||||
assert_eq!(object.data.service_id, "ISPAPI EPP Server");
|
assert_eq!(object.data.service_id, "ISPAPI EPP Server");
|
||||||
assert_eq!(object.data.service_date, "2021-07-25T14:51:17.0Z");
|
assert_eq!(object.data.service_date, "2021-07-25T14:51:17.0Z");
|
||||||
|
@ -75,7 +75,7 @@ mod response {
|
||||||
#[test]
|
#[test]
|
||||||
fn error() {
|
fn error() {
|
||||||
let xml = get_xml("response/error.xml").unwrap();
|
let xml = get_xml("response/error.xml").unwrap();
|
||||||
let object = EppObject::<ResponseStatus>::deserialize(xml.as_str()).unwrap();
|
let object = ResultDocument::deserialize(xml.as_str()).unwrap();
|
||||||
|
|
||||||
assert_eq!(object.data.result.code, 2303);
|
assert_eq!(object.data.result.code, 2303);
|
||||||
assert_eq!(object.data.result.message, "Object does not exist".into());
|
assert_eq!(object.data.result.message, "Object does not exist".into());
|
||||||
|
@ -637,7 +637,11 @@ mod response {
|
||||||
#[test]
|
#[test]
|
||||||
fn rgp_restore_response() {
|
fn rgp_restore_response() {
|
||||||
let xml = get_xml("response/extensions/rgp_restore.xml").unwrap();
|
let xml = get_xml("response/extensions/rgp_restore.xml").unwrap();
|
||||||
let object = DomainUpdate::<RgpRestoreRequest>::deserialize_response(xml.as_str()).unwrap();
|
let object =
|
||||||
|
DomainUpdate::<rgp::Update<rgp::request::RgpRestoreRequest>>::deserialize_response(
|
||||||
|
xml.as_str(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let ext = object.extension.unwrap();
|
let ext = object.extension.unwrap();
|
||||||
|
|
||||||
|
@ -650,7 +654,11 @@ mod response {
|
||||||
#[test]
|
#[test]
|
||||||
fn rgp_restore_domain_info_response() {
|
fn rgp_restore_domain_info_response() {
|
||||||
let xml = get_xml("response/extensions/domain_info_rgp.xml").unwrap();
|
let xml = get_xml("response/extensions/domain_info_rgp.xml").unwrap();
|
||||||
let object = DomainInfo::<RgpRestoreRequest>::deserialize_response(xml.as_str()).unwrap();
|
let object =
|
||||||
|
DomainInfo::<rgp::Update<rgp::request::RgpRestoreRequest>>::deserialize_response(
|
||||||
|
xml.as_str(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let ext = object.extension.unwrap();
|
let ext = object.extension.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ mod request {
|
||||||
use crate::common::HostObjList;
|
use crate::common::HostObjList;
|
||||||
use crate::common::NoExtension;
|
use crate::common::NoExtension;
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
Address, ContactStatus, DomainAuthInfo, DomainContact, DomainStatus, EppObject, HostAddr,
|
Address, ContactStatus, DomainAuthInfo, DomainContact, DomainStatus, HostAddr, HostAttr,
|
||||||
HostAttr, HostStatus, Phone, PostalInfo,
|
HostStatus, Phone, PostalInfo,
|
||||||
};
|
};
|
||||||
use crate::contact::check::ContactCheck;
|
use crate::contact::check::ContactCheck;
|
||||||
use crate::contact::create::ContactCreate;
|
use crate::contact::create::ContactCreate;
|
||||||
|
@ -32,9 +32,8 @@ mod request {
|
||||||
use crate::extensions::consolidate;
|
use crate::extensions::consolidate;
|
||||||
use crate::extensions::consolidate::GMonthDay;
|
use crate::extensions::consolidate::GMonthDay;
|
||||||
use crate::extensions::namestore::NameStore;
|
use crate::extensions::namestore::NameStore;
|
||||||
use crate::extensions::rgp::report::RgpRestoreReport;
|
use crate::extensions::rgp::{self, report::RgpRestoreReport, request::RgpRestoreRequest};
|
||||||
use crate::extensions::rgp::request::RgpRestoreRequest;
|
use crate::hello::HelloDocument;
|
||||||
use crate::hello::Hello;
|
|
||||||
use crate::host::check::HostCheck;
|
use crate::host::check::HostCheck;
|
||||||
use crate::host::create::HostCreate;
|
use crate::host::create::HostCreate;
|
||||||
use crate::host::delete::HostDelete;
|
use crate::host::delete::HostDelete;
|
||||||
|
@ -54,7 +53,7 @@ mod request {
|
||||||
#[test]
|
#[test]
|
||||||
fn hello() {
|
fn hello() {
|
||||||
let xml = get_xml("request/hello.xml").unwrap();
|
let xml = get_xml("request/hello.xml").unwrap();
|
||||||
let serialized = EppObject::<Hello>::build(Hello).serialize().unwrap();
|
let serialized = HelloDocument::default().serialize().unwrap();
|
||||||
|
|
||||||
assert_eq!(xml, serialized);
|
assert_eq!(xml, serialized);
|
||||||
}
|
}
|
||||||
|
@ -527,9 +526,11 @@ mod request {
|
||||||
fn rgp_restore_request() {
|
fn rgp_restore_request() {
|
||||||
let xml = get_xml("request/extensions/rgp_restore_request.xml").unwrap();
|
let xml = get_xml("request/extensions/rgp_restore_request.xml").unwrap();
|
||||||
|
|
||||||
let domain_restore_request = RgpRestoreRequest::new();
|
let domain_restore_request = rgp::Update {
|
||||||
|
data: RgpRestoreRequest::default(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut object = DomainUpdate::<RgpRestoreReport>::new("eppdev.com")
|
let mut object = DomainUpdate::<rgp::Update<RgpRestoreRequest>>::new("eppdev.com")
|
||||||
.with_extension(domain_restore_request);
|
.with_extension(domain_restore_request);
|
||||||
|
|
||||||
let change_info = DomainChangeInfo {
|
let change_info = DomainChangeInfo {
|
||||||
|
@ -561,7 +562,8 @@ mod request {
|
||||||
];
|
];
|
||||||
let other = "Supporting information goes here.";
|
let other = "Supporting information goes here.";
|
||||||
|
|
||||||
let domain_restore_report = RgpRestoreReport::new(
|
let domain_restore_report = rgp::Update {
|
||||||
|
data: RgpRestoreReport::new(
|
||||||
pre_data,
|
pre_data,
|
||||||
post_data,
|
post_data,
|
||||||
deleted_at,
|
deleted_at,
|
||||||
|
@ -569,9 +571,10 @@ mod request {
|
||||||
restore_reason,
|
restore_reason,
|
||||||
statements,
|
statements,
|
||||||
other,
|
other,
|
||||||
);
|
),
|
||||||
|
};
|
||||||
|
|
||||||
let mut object = DomainUpdate::<RgpRestoreReport>::new("eppdev.com")
|
let mut object = DomainUpdate::<rgp::Update<RgpRestoreReport>>::new("eppdev.com")
|
||||||
.with_extension(domain_restore_report);
|
.with_extension(domain_restore_report);
|
||||||
|
|
||||||
let change_info = DomainChangeInfo {
|
let change_info = DomainChangeInfo {
|
||||||
|
@ -607,10 +610,10 @@ mod request {
|
||||||
|
|
||||||
let exp = GMonthDay::new(5, 31, None).unwrap();
|
let exp = GMonthDay::new(5, 31, None).unwrap();
|
||||||
|
|
||||||
let consolidate_ext = consolidate::Sync::new(exp);
|
let consolidate_ext = consolidate::Update::new(exp);
|
||||||
|
|
||||||
let mut object =
|
let mut object =
|
||||||
DomainUpdate::<consolidate::Sync>::new("eppdev.com").with_extension(consolidate_ext);
|
DomainUpdate::<consolidate::Update>::new("eppdev.com").with_extension(consolidate_ext);
|
||||||
|
|
||||||
object.info(DomainChangeInfo {
|
object.info(DomainChangeInfo {
|
||||||
registrant: None,
|
registrant: None,
|
||||||
|
|
|
@ -3,26 +3,30 @@
|
||||||
use quick_xml::de::from_str;
|
use quick_xml::de::from_str;
|
||||||
use quick_xml::se;
|
use quick_xml::se;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use std::{error::Error, fmt::Debug};
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::common::{ElementName, EppObject};
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
|
||||||
pub const EPP_XML_HEADER: &str = r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?>"#;
|
pub const EPP_XML_HEADER: &str = r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?>"#;
|
||||||
|
|
||||||
impl<T: Serialize + DeserializeOwned + ElementName + Debug> EppXml for EppObject<T> {
|
/// Trait to be implemented by serializers. Currently the only included serializer is `quick-xml`
|
||||||
type Output = EppObject<T>;
|
pub trait EppXml: Sized {
|
||||||
|
|
||||||
/// Serializes the EppObject instance to an EPP XML document
|
/// Serializes the EppObject instance to an EPP XML document
|
||||||
fn serialize(&self) -> Result<String, Box<dyn Error>> {
|
fn serialize(&self) -> Result<String, Box<dyn Error>>
|
||||||
|
where
|
||||||
|
Self: Serialize,
|
||||||
|
{
|
||||||
let epp_xml = format!("{}\r\n{}", EPP_XML_HEADER, se::to_string(self)?);
|
let epp_xml = format!("{}\r\n{}", EPP_XML_HEADER, se::to_string(self)?);
|
||||||
|
|
||||||
Ok(epp_xml)
|
Ok(epp_xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes an EPP XML document to an EppObject instance
|
/// Deserializes an EPP XML document to an EppObject instance
|
||||||
fn deserialize(epp_xml: &str) -> Result<Self::Output, error::Error> {
|
fn deserialize(epp_xml: &str) -> Result<Self, error::Error>
|
||||||
let object: Self::Output = match from_str(epp_xml) {
|
where
|
||||||
|
Self: DeserializeOwned + Sized,
|
||||||
|
{
|
||||||
|
let object: Self = match from_str(epp_xml) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(error::Error::EppDeserializationError(format!(
|
return Err(error::Error::EppDeserializationError(format!(
|
||||||
|
@ -35,11 +39,3 @@ impl<T: Serialize + DeserializeOwned + ElementName + Debug> EppXml for EppObject
|
||||||
Ok(object)
|
Ok(object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait to be implemented by serializers. Currently the only included serializer is `quick-xml`
|
|
||||||
pub trait EppXml {
|
|
||||||
type Output: Debug;
|
|
||||||
|
|
||||||
fn serialize(&self) -> Result<String, Box<dyn Error>>;
|
|
||||||
fn deserialize(epp_xml: &str) -> Result<Self::Output, error::Error>;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue