new transact() function
This commit is contained in:
parent
458f39a6ed
commit
898f8a2a2f
|
@ -4,3 +4,4 @@
|
||||||
/config
|
/config
|
||||||
/epp-client/examples
|
/epp-client/examples
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
**/secrets
|
||||||
|
|
|
@ -51,3 +51,59 @@ pub fn element_name_derive(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
element_name_macro(&ast)
|
element_name_macro(&ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn epp_request_macro(ast: &syn::DeriveInput) -> proc_macro::TokenStream {
|
||||||
|
let name = &ast.ident;
|
||||||
|
let attr = &ast.attrs[0];
|
||||||
|
let mut response_type: Option<syn::Ident> = None;
|
||||||
|
let (impl_generics, type_generics, _) = &ast.generics.split_for_impl();
|
||||||
|
|
||||||
|
if attr.path.is_ident("response") {
|
||||||
|
match attr.parse_meta() {
|
||||||
|
Ok(syn::Meta::List(meta)) => {
|
||||||
|
let item = &meta.nested[0];
|
||||||
|
match item {
|
||||||
|
syn::NestedMeta::Meta(syn::Meta::Path(p)) => {
|
||||||
|
response_type = Some(p.get_ident().unwrap().clone());
|
||||||
|
}
|
||||||
|
_ => panic!("Failed to parse args for epp_types"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Failed to parse args for epp_types"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(resp) = response_type {
|
||||||
|
let implement = quote::quote! {
|
||||||
|
impl #impl_generics EppRequest for #name #type_generics {
|
||||||
|
type Output = #resp;
|
||||||
|
|
||||||
|
fn deserialize_response(&self, epp_xml: &str) -> Result<Self::Output, Box<dyn std::error::Error>> {
|
||||||
|
match Self::Output::deserialize(epp_xml) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => Err(format!("epp-client: Deserialization error: {}", e).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_request(&self) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
match &self.0.serialize() {
|
||||||
|
Ok(serialized) => Ok(serialized.to_string()),
|
||||||
|
Err(e) => Err(format!("epp-client: Serialization error: {}", e).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
implement.into()
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"response() needs 1 argument, a response type that implements epp_client::epp::xml::EppXml"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(EppRequest, attributes(response))]
|
||||||
|
pub fn epp_request_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let ast = syn::parse(input).expect("Error while parsing EppTransaction macro input");
|
||||||
|
|
||||||
|
epp_request_macro(&ast)
|
||||||
|
}
|
||||||
|
|
|
@ -26,3 +26,4 @@ webpki-roots = "0.22.1"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio-test = "0.4"
|
tokio-test = "0.4"
|
||||||
regex = "1.5"
|
regex = "1.5"
|
||||||
|
toml = "0.5"
|
||||||
|
|
|
@ -51,7 +51,7 @@ use std::{error::Error, fmt::Debug};
|
||||||
|
|
||||||
use crate::config::EppClientConfig;
|
use crate::config::EppClientConfig;
|
||||||
use crate::connection::registry::{epp_connect, EppConnection};
|
use crate::connection::registry::{epp_connect, EppConnection};
|
||||||
use crate::epp::request::{generate_client_tr_id, EppHello, EppLogin, EppLogout};
|
use crate::epp::request::{generate_client_tr_id, EppHello, EppLogin, EppLogout, EppRequest};
|
||||||
use crate::epp::response::{
|
use crate::epp::response::{
|
||||||
EppCommandResponse, EppCommandResponseError, EppGreeting, EppLoginResponse, EppLogoutResponse,
|
EppCommandResponse, EppCommandResponseError, EppGreeting, EppLoginResponse, EppLogoutResponse,
|
||||||
};
|
};
|
||||||
|
@ -158,6 +158,25 @@ impl EppClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn transact_new<T: EppRequest + Debug>(
|
||||||
|
&mut self,
|
||||||
|
request: &T,
|
||||||
|
) -> Result<<T as EppRequest>::Output, error::Error> {
|
||||||
|
let epp_xml = request.serialize_request()?;
|
||||||
|
|
||||||
|
let response = self.connection.transact(&epp_xml).await?;
|
||||||
|
|
||||||
|
let status = EppCommandResponse::deserialize(&response)?;
|
||||||
|
|
||||||
|
if status.data.result.code < 2000 {
|
||||||
|
let response = request.deserialize_response(&response)?;
|
||||||
|
Ok(response)
|
||||||
|
} else {
|
||||||
|
let epp_error = EppCommandResponseError::deserialize(&response)?;
|
||||||
|
Err(error::Error::EppCommandError(epp_error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetches the username used in the registry connection
|
/// Fetches the username used in the registry connection
|
||||||
pub fn username(&self) -> String {
|
pub fn username(&self) -> String {
|
||||||
self.credentials.0.to_string()
|
self.credentials.0.to_string()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod check;
|
|
@ -0,0 +1,17 @@
|
||||||
|
use epp_client_macros::*;
|
||||||
|
|
||||||
|
use crate::epp::request::domain::check::EppDomainCheck;
|
||||||
|
use crate::epp::request::EppRequest;
|
||||||
|
use crate::epp::response::domain::check::EppDomainCheckResponse;
|
||||||
|
use crate::epp::xml::EppXml;
|
||||||
|
|
||||||
|
#[derive(EppRequest, Debug)]
|
||||||
|
#[response(EppDomainCheckResponse)]
|
||||||
|
pub struct Request(EppDomainCheck);
|
||||||
|
|
||||||
|
impl Request {
|
||||||
|
/// Creates a new Request for a domain check
|
||||||
|
pub fn new(domains: Vec<&str>, client_tr_id: &str) -> Request {
|
||||||
|
Request(EppDomainCheck::new(domains, client_tr_id))
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,15 +5,31 @@ pub mod domain;
|
||||||
pub mod host;
|
pub mod host;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
|
||||||
|
use epp_client_macros::*;
|
||||||
|
|
||||||
use serde::{ser::SerializeStruct, ser::Serializer, Deserialize, Serialize};
|
use serde::{ser::SerializeStruct, ser::Serializer, Deserialize, Serialize};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use crate::epp::object::{
|
use crate::epp::object::{
|
||||||
ElementName, EmptyTag, EppObject, Extension, Options, ServiceExtension, Services, StringValue,
|
ElementName, EmptyTag, EppObject, Extension, Options, ServiceExtension, Services, StringValue,
|
||||||
};
|
};
|
||||||
use crate::epp::xml::{EPP_CONTACT_XMLNS, EPP_DOMAIN_XMLNS, EPP_HOST_XMLNS, EPP_LANG, EPP_VERSION};
|
use crate::epp::xml::{
|
||||||
use epp_client_macros::*;
|
EppXml, EPP_CONTACT_XMLNS, EPP_DOMAIN_XMLNS, EPP_HOST_XMLNS, EPP_LANG, EPP_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Trait to set correct value for xml tags when tags are being generated from generic types
|
||||||
|
pub trait EppRequest {
|
||||||
|
type Output: EppXml + Debug;
|
||||||
|
|
||||||
|
fn deserialize_response(
|
||||||
|
&self,
|
||||||
|
epp_xml: &str,
|
||||||
|
) -> Result<Self::Output, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
fn serialize_request(&self) -> Result<String, Box<dyn std::error::Error>>;
|
||||||
|
}
|
||||||
|
|
||||||
/// Type corresponding to the <command> tag in an EPP XML request
|
/// Type corresponding to the <command> tag in an EPP XML request
|
||||||
/// without an <extension> tag
|
/// without an <extension> tag
|
||||||
|
|
|
@ -102,6 +102,7 @@ extern crate log;
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod connection;
|
pub mod connection;
|
||||||
|
pub mod domain;
|
||||||
pub mod epp;
|
pub mod epp;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub use connection::client::EppClient;
|
pub use connection::client::EppClient;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
use super::CLTRID;
|
||||||
|
use super::RESOURCES_DIR;
|
||||||
|
use crate::config::EppClientConfig;
|
||||||
|
use crate::domain;
|
||||||
|
use crate::EppClient;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use toml;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[ignore]
|
||||||
|
async fn domain_check() {
|
||||||
|
let config_file = format!("{}/{}", RESOURCES_DIR, "secrets/epp-client.toml");
|
||||||
|
let config_path = Path::new(config_file.as_str());
|
||||||
|
let contents = &fs::read_to_string(config_path).unwrap();
|
||||||
|
|
||||||
|
let config: EppClientConfig = toml::from_str(contents).unwrap();
|
||||||
|
|
||||||
|
let mut client = match EppClient::new(&config, "testing").await {
|
||||||
|
Ok(client) => client,
|
||||||
|
Err(e) => panic!("Failed to create EppClient: {}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
let domains = vec!["eppdev.com", "eppdev.net"];
|
||||||
|
let request = domain::check::Request::new(domains, CLTRID);
|
||||||
|
|
||||||
|
client.transact_new(&request).await.unwrap();
|
||||||
|
|
||||||
|
client.logout().await.unwrap();
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
//! Module for automated tests
|
//! Module for automated tests
|
||||||
|
|
||||||
pub mod de;
|
pub mod de;
|
||||||
|
pub mod int;
|
||||||
pub mod se;
|
pub mod se;
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
mod request {
|
mod request {
|
||||||
use super::super::get_xml;
|
use super::super::get_xml;
|
||||||
use super::super::CLTRID;
|
use super::super::CLTRID;
|
||||||
|
use crate::domain;
|
||||||
use crate::epp::object::data::{
|
use crate::epp::object::data::{
|
||||||
Address, ContactStatus, DomainAuthInfo, DomainContact, DomainStatus, HostAddr, HostAttr,
|
Address, ContactStatus, DomainAuthInfo, DomainContact, DomainStatus, HostAddr, HostAttr,
|
||||||
HostStatus, Phone, PostalInfo,
|
HostStatus, Phone, PostalInfo,
|
||||||
};
|
};
|
||||||
use crate::epp::request::{EppHello, EppLogin, EppLogout};
|
use crate::epp::object::StringValueTrait;
|
||||||
|
use crate::epp::request::{EppHello, EppLogin, EppLogout, EppRequest};
|
||||||
use crate::epp::xml::EppXml;
|
use crate::epp::xml::EppXml;
|
||||||
use crate::epp::*;
|
use crate::epp::*;
|
||||||
use chrono::{DateTime, NaiveDate};
|
use chrono::{DateTime, NaiveDate};
|
||||||
|
@ -139,6 +141,17 @@ mod request {
|
||||||
assert_eq!(xml, serialized);
|
assert_eq!(xml, serialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wrapped_domain_check() {
|
||||||
|
let xml = get_xml("request/domain/check.xml").unwrap();
|
||||||
|
|
||||||
|
let object = domain::check::Request::new(vec!["eppdev.com", "eppdev.net"], CLTRID);
|
||||||
|
|
||||||
|
let serialized = object.serialize_request().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(xml, serialized);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn domain_create() {
|
fn domain_create() {
|
||||||
let xml = get_xml("request/domain/create.xml").unwrap();
|
let xml = get_xml("request/domain/create.xml").unwrap();
|
||||||
|
|
Loading…
Reference in New Issue