new transact() function
This commit is contained in:
parent
458f39a6ed
commit
898f8a2a2f
|
@ -4,3 +4,4 @@
|
|||
/config
|
||||
/epp-client/examples
|
||||
Cargo.lock
|
||||
**/secrets
|
||||
|
|
|
@ -51,3 +51,59 @@ pub fn element_name_derive(input: TokenStream) -> TokenStream {
|
|||
|
||||
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]
|
||||
tokio-test = "0.4"
|
||||
regex = "1.5"
|
||||
toml = "0.5"
|
||||
|
|
|
@ -51,7 +51,7 @@ use std::{error::Error, fmt::Debug};
|
|||
|
||||
use crate::config::EppClientConfig;
|
||||
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::{
|
||||
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
|
||||
pub fn username(&self) -> 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 message;
|
||||
|
||||
use epp_client_macros::*;
|
||||
|
||||
use serde::{ser::SerializeStruct, ser::Serializer, Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use std::fmt::Debug;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crate::epp::object::{
|
||||
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 epp_client_macros::*;
|
||||
use crate::epp::xml::{
|
||||
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
|
||||
/// without an <extension> tag
|
||||
|
|
|
@ -102,6 +102,7 @@ extern crate log;
|
|||
|
||||
pub mod config;
|
||||
pub mod connection;
|
||||
pub mod domain;
|
||||
pub mod epp;
|
||||
pub mod error;
|
||||
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
|
||||
|
||||
pub mod de;
|
||||
pub mod int;
|
||||
pub mod se;
|
||||
|
||||
use regex::Regex;
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
mod request {
|
||||
use super::super::get_xml;
|
||||
use super::super::CLTRID;
|
||||
use crate::domain;
|
||||
use crate::epp::object::data::{
|
||||
Address, ContactStatus, DomainAuthInfo, DomainContact, DomainStatus, HostAddr, HostAttr,
|
||||
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::*;
|
||||
use chrono::{DateTime, NaiveDate};
|
||||
|
@ -139,6 +141,17 @@ mod request {
|
|||
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]
|
||||
fn domain_create() {
|
||||
let xml = get_xml("request/domain/create.xml").unwrap();
|
||||
|
|
Loading…
Reference in New Issue