Skip to content

Commit

Permalink
Merge pull request #91 from icann/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
anewton1998 authored Dec 3, 2024
2 parents 707d906 + 82e33f5 commit 717b53a
Show file tree
Hide file tree
Showing 44 changed files with 3,020 additions and 934 deletions.
1,356 changes: 700 additions & 656 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ members = [
resolver = "2"

[workspace.package]
version = "0.0.18"
version = "0.0.19"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/icann/icann-rdap"
Expand Down Expand Up @@ -81,6 +81,10 @@ http = "1.0"
# hyper (http implementation used by axum)
hyper = { version = "1.0", features = ["full"] }

# JSONPath
jsonpath-rust = "=0.5.0"
jsonpath_lib = "0.3.0"

# internationalized domain names for applications
idna = "0.5"

Expand Down Expand Up @@ -122,7 +126,7 @@ strum = "0.24"
strum_macros = "0.24"

# terminal markdown generator
termimad = "0.26"
termimad = "0.31"

# error macros
thiserror = "1.0"
Expand Down
4 changes: 2 additions & 2 deletions icann-rdap-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ path = "src/main.rs"

[dependencies]

icann-rdap-client = { version = "0.0.18", path = "../icann-rdap-client" }
icann-rdap-common = { version = "0.0.18", path = "../icann-rdap-common" }
icann-rdap-client = { version = "0.0.19", path = "../icann-rdap-client" }
icann-rdap-common = { version = "0.0.19", path = "../icann-rdap-common" }

anyhow.workspace = true
clap.workspace = true
Expand Down
83 changes: 71 additions & 12 deletions icann-rdap-cli/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,33 @@ use icann_rdap_client::query::{
qtype::QueryType,
};
use icann_rdap_common::{
cache::HttpData,
httpdata::HttpData,
iana::{BootstrapRegistry, IanaRegistry, IanaRegistryType},
};
use reqwest::Client;
use tracing::debug;

use crate::{dirs::bootstrap_cache_path, error::CliError};

/// Defines the type of bootstrapping to use.
pub(crate) enum BootstrapType {
None,
/// Use RFC 9224 bootstrapping.
///
/// This is the typical bootstrapping for RDAP as defined by RFC 9224.
Rfc9224,

/// Use the supplied URL.
///
/// Essentially, this means no bootstrapping as the client is being given
/// a full URL.
Url(String),
Tag(String),

/// Use a hint.
///
/// This will try to find an authoritative server by cycling through the various
/// bootstrap registries in the following order: object tags, TLDs, IP addresses,
/// ASNs.
Hint(String),
}

pub(crate) async fn get_base_url(
Expand All @@ -40,17 +55,61 @@ pub(crate) async fn get_base_url(
let store = FileCacheBootstrapStore;

match bootstrap_type {
BootstrapType::None => Ok(qtype_to_bootstrap_url(client, &store, query_type, |reg| {
BootstrapType::Rfc9224 => Ok(qtype_to_bootstrap_url(client, &store, query_type, |reg| {
debug!("Fetching IANA registry {}", reg.url())
})
.await?),
BootstrapType::Url(url) => Ok(url.to_owned()),
BootstrapType::Tag(tag) => {
BootstrapType::Hint(hint) => {
fetch_bootstrap(&IanaRegistryType::RdapObjectTags, client, &store, |_reg| {
debug!("Fetching IANA RDAP Object Tag Registry")
})
.await?;
Ok(store.get_tag_urls(tag)?.preferred_url()?)
if let Ok(urls) = store.get_tag_urls(hint) {
Ok(urls.preferred_url()?)
} else {
fetch_bootstrap(
&IanaRegistryType::RdapBootstrapDns,
client,
&store,
|_reg| debug!("Fetching IANA RDAP DNS Registry"),
)
.await?;
if let Ok(urls) = store.get_dns_urls(hint) {
Ok(urls.preferred_url()?)
} else {
fetch_bootstrap(
&IanaRegistryType::RdapBootstrapIpv4,
client,
&store,
|_reg| debug!("Fetching IANA RDAP IPv4 Registry"),
)
.await?;
if let Ok(urls) = store.get_ipv4_urls(hint) {
Ok(urls.preferred_url()?)
} else {
fetch_bootstrap(
&IanaRegistryType::RdapBootstrapIpv6,
client,
&store,
|_reg| debug!("Fetching IANA RDAP IPv6 Registry"),
)
.await?;
if let Ok(urls) = store.get_ipv6_urls(hint) {
Ok(urls.preferred_url()?)
} else {
fetch_bootstrap(
&IanaRegistryType::RdapBootstrapAsn,
client,
&store,
|_reg| debug!("Fetching IANA RDAP ASN Registry"),
)
.await?;
Ok(store.get_asn_urls(hint)?.preferred_url()?)
}
}
}
}
}
}
}
Expand Down Expand Up @@ -138,7 +197,7 @@ where
mod test {
use icann_rdap_client::query::{bootstrap::PreferredUrl, qtype::QueryType};
use icann_rdap_common::{
cache::HttpData,
httpdata::HttpData,
iana::{IanaRegistry, IanaRegistryType},
};
use serial_test::serial;
Expand Down Expand Up @@ -190,7 +249,7 @@ mod test {
bs.put_bootstrap_registry(
&IanaRegistryType::RdapBootstrapDns,
iana,
HttpData::now().host("example.com").build(),
HttpData::example().build(),
)
.expect("put iana registry");

Expand Down Expand Up @@ -244,7 +303,7 @@ mod test {
bs.put_bootstrap_registry(
&IanaRegistryType::RdapBootstrapAsn,
iana,
HttpData::now().host("example.com").build(),
HttpData::example().build(),
)
.expect("put iana registry");

Expand Down Expand Up @@ -298,7 +357,7 @@ mod test {
bs.put_bootstrap_registry(
&IanaRegistryType::RdapBootstrapIpv4,
iana,
HttpData::now().host("example.com").build(),
HttpData::example().build(),
)
.expect("put iana registry");

Expand Down Expand Up @@ -352,7 +411,7 @@ mod test {
bs.put_bootstrap_registry(
&IanaRegistryType::RdapBootstrapIpv6,
iana,
HttpData::now().host("example.com").build(),
HttpData::example().build(),
)
.expect("put iana registry");

Expand Down Expand Up @@ -409,7 +468,7 @@ mod test {
bs.put_bootstrap_registry(
&IanaRegistryType::RdapObjectTags,
iana,
HttpData::now().host("example.com").build(),
HttpData::example().build(),
)
.expect("put iana registry");

Expand Down
38 changes: 38 additions & 0 deletions icann-rdap-cli/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::process::{ExitCode, Termination};

use icann_rdap_client::RdapClientError;
use icann_rdap_common::iana::IanaResponseError;
use minus::MinusError;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum CliError {
#[error("No errors encountered")]
Success,
#[error(transparent)]
RdapClient(#[from] RdapClientError),
#[error(transparent)]
Expand All @@ -25,4 +29,38 @@ pub enum CliError {
InvalidBootstrap,
#[error("Bootstrap not found")]
BootstrapNotFound,
#[error("No registrar found")]
NoRegistrarFound,
#[error("No registry found")]
NoRegistryFound,
}

impl Termination for CliError {
fn report(self) -> std::process::ExitCode {
let exit_code: u8 = match self {
// Success
CliError::Success => 0,

// Internal Errors
CliError::Termimad(_) => 10,
CliError::Minus(_) => 11,

// I/O Errors
CliError::IoError(_) => 40,
CliError::RdapClient(_) => 41,

// RDAP Errors
CliError::Json(_) => 100,
CliError::Iana(_) => 101,
CliError::InvalidBootstrap => 102,
CliError::BootstrapNotFound => 103,
CliError::NoRegistrarFound => 104,
CliError::NoRegistryFound => 105,

// User Errors
CliError::UnknownOutputType => 200,
CliError::ErrorOnChecks => 201,
};
ExitCode::from(exit_code)
}
}
Loading

0 comments on commit 717b53a

Please sign in to comment.