Skip to content

Commit 707d906

Browse files
authored
Merge pull request #83 from icann/dev
Release v0.0.18
2 parents 92e1d91 + 706922e commit 707d906

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+2839
-758
lines changed

Cargo.lock

+66-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ members = [
88
resolver = "2"
99

1010
[workspace.package]
11-
version = "0.0.17"
11+
version = "0.0.18"
1212
edition = "2021"
1313
license = "MIT OR Apache-2.0"
1414
repository = "https://github.com/icann/icann-rdap"
1515
keywords = ["whois", "rdap"]
1616

1717
[workspace.dependencies]
1818

19+
# for suffix string searchs
20+
ab-radix-trie = "0.2.1"
21+
1922
# easy error handling
2023
anyhow = "1.0"
2124

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ This repository contains open source code written by the Internet Corporation fo
55
for use with the Registry Data Access Protocol (RDAP). RDAP is standard of the [IETF](https://ietf.org/), and extensions
66
to RDAP are a current work activity of the IETF's [REGEXT working group](https://datatracker.ietf.org/wg/regext/documents/).
77
More information on ICANN's role in RDAP can be found [here](https://www.icann.org/rdap).
8+
General information on RDAP can be found [here](https://rdap.rcode3.com/).
89

910
About
1011
-----
1112

12-
This repository hosts 4 separate Rust crates:
13+
This repository hosts 4 separate packages (i.e. Rust crates):
1314

14-
* [icann-rdap-cli](icann-rdap-cli/README.md) is the Command Line Interface client.
15+
* [icann-rdap-cli](icann-rdap-cli/README.md) is the Command Line Interface client. This package produces an executable binary.
1516
* [icann-rdap-client](icann-rdap-client/README.md) is a library handling making RDAP requests.
1617
* [icann-rdap-common](icann-rdap-common/README.md) is a library of RDAP structures.
17-
* [icann-rdap-srv](icann-rdap-srv/README.md) is a simple, in-memory RDAP server.
18+
* [icann-rdap-srv](icann-rdap-srv/README.md) is a simple, in-memory RDAP server. This package produces multiple executable binaries.
1819

1920
License
2021
-------

icann-rdap-cli/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ path = "src/main.rs"
1414

1515
[dependencies]
1616

17-
icann-rdap-client = { version = "0.0.17", path = "../icann-rdap-client" }
18-
icann-rdap-common = { version = "0.0.17", path = "../icann-rdap-common" }
17+
icann-rdap-client = { version = "0.0.18", path = "../icann-rdap-client" }
18+
icann-rdap-common = { version = "0.0.18", path = "../icann-rdap-common" }
1919

2020
anyhow.workspace = true
2121
clap.workspace = true

icann-rdap-cli/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ by the Internet Corporation for Assigned Names and Numbers [(ICANN)](https://www
66
RDAP is standard of the [IETF](https://ietf.org/), and extensions
77
to RDAP are a current work activity of the IETF's [REGEXT working group](https://datatracker.ietf.org/wg/regext/documents/).
88
More information on ICANN's role in RDAP can be found [here](https://www.icann.org/rdap).
9+
General information on RDAP can be found [here](https://rdap.rcode3.com/).
910

1011
Installing the RDAP Client
1112
--------------------------
@@ -79,7 +80,7 @@ Output Format
7980
-------------
8081

8182
By default, the client will attempt to determine the output format of the information. If it determines the shell
82-
is interactive, output will be in `rendered-markdown`. Otherwise the output will be JSON.
83+
is interactive, output will be in `rendered-markdown`. Otherwise, the output will be JSON.
8384

8485
You can explicitly control this behavior using the `-O` command argument or the `RDAP_OUTPUT` environment variable
8586
(see below).

icann-rdap-cli/src/query.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ async fn do_domain_query<'a, W: std::io::Write>(
8080
let mut transactions = RequestResponses::new();
8181
let base_url = get_base_url(&processing_params.bootstrap_type, client, query_type).await?;
8282
let response = do_request(&base_url, query_type, processing_params, client).await;
83+
let registrar_response;
8384
match response {
8485
Ok(response) => {
8586
let source_host = response.http_data.host.to_owned();
@@ -106,11 +107,12 @@ async fn do_domain_query<'a, W: std::io::Write>(
106107
if let Some(url) = get_related_link(&response.rdap).first() {
107108
info!("Querying domain name from registrar.");
108109
let query_type = QueryType::Url(url.to_string());
109-
let registrar_response =
110+
let registrar_response_result =
110111
do_request(&base_url, &query_type, processing_params, client).await;
111-
match registrar_response {
112-
Ok(registrar_response) => {
113-
regr_source_host = registrar_response.http_data.host;
112+
match registrar_response_result {
113+
Ok(response_data) => {
114+
registrar_response = response_data;
115+
regr_source_host = registrar_response.http_data.host.to_owned();
114116
regr_req_data = RequestData {
115117
req_number: 2,
116118
source_host: &regr_source_host,
@@ -119,7 +121,7 @@ async fn do_domain_query<'a, W: std::io::Write>(
119121
transactions = do_output(
120122
processing_params,
121123
&regr_req_data,
122-
&response,
124+
&registrar_response,
123125
write,
124126
transactions,
125127
)?;
@@ -363,18 +365,22 @@ fn get_related_link(rdap_response: &RdapResponse) -> Vec<&str> {
363365
let urls: Vec<&str> = links
364366
.iter()
365367
.filter(|l| {
366-
if let Some(rel) = &l.rel {
367-
if let Some(media_type) = &l.media_type {
368-
rel.eq_ignore_ascii_case("related")
369-
&& media_type.eq_ignore_ascii_case(RDAP_MEDIA_TYPE)
368+
if l.href.as_ref().is_some() {
369+
if let Some(rel) = &l.rel {
370+
if let Some(media_type) = &l.media_type {
371+
rel.eq_ignore_ascii_case("related")
372+
&& media_type.eq_ignore_ascii_case(RDAP_MEDIA_TYPE)
373+
} else {
374+
false
375+
}
370376
} else {
371377
false
372378
}
373379
} else {
374380
false
375381
}
376382
})
377-
.map(|l| l.href.as_str())
383+
.map(|l| l.href.as_ref().unwrap().as_str())
378384
.collect::<Vec<&str>>();
379385
urls
380386
} else {

icann-rdap-cli/src/request.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -53,33 +53,35 @@ pub(crate) async fn do_request(
5353
let response = rdap_url_request(&query_url, client).await?;
5454
if !processing_params.no_cache {
5555
if let Some(self_link) = response.rdap.get_self_link() {
56-
if response.http_data.should_cache() {
57-
let data = serde_json::to_string_pretty(&response)?;
58-
let cache_contents = response.http_data.to_lines(&data)?;
59-
let query_url = query_type.query_url(base_url)?;
60-
let file_name = format!(
61-
"{}.cache",
62-
PctString::encode(query_url.chars(), URIReserved)
63-
);
64-
debug!("Saving response to cache file {file_name}");
65-
let path = rdap_cache_path().join(file_name);
66-
fs::write(path, &cache_contents)?;
67-
if query_url != self_link.href {
56+
if let Some(self_link_href) = &self_link.href {
57+
if response.http_data.should_cache() {
58+
let data = serde_json::to_string_pretty(&response)?;
59+
let cache_contents = response.http_data.to_lines(&data)?;
60+
let query_url = query_type.query_url(base_url)?;
6861
let file_name = format!(
6962
"{}.cache",
70-
PctString::encode(self_link.href.chars(), URIReserved)
63+
PctString::encode(query_url.chars(), URIReserved)
7164
);
7265
debug!("Saving response to cache file {file_name}");
7366
let path = rdap_cache_path().join(file_name);
7467
fs::write(path, &cache_contents)?;
68+
if query_url != *self_link_href {
69+
let file_name = format!(
70+
"{}.cache",
71+
PctString::encode(self_link_href.chars(), URIReserved)
72+
);
73+
debug!("Saving response to cache file {file_name}");
74+
let path = rdap_cache_path().join(file_name);
75+
fs::write(path, &cache_contents)?;
76+
}
77+
} else {
78+
debug!("Not caching data according to server policy.");
79+
debug!("Expires header: {:?}", &response.http_data.expires);
80+
debug!(
81+
"Cache-control header: {:?}",
82+
&response.http_data.cache_control
83+
);
7584
}
76-
} else {
77-
debug!("Not caching data according to server policy.");
78-
debug!("Expires header: {:?}", &response.http_data.expires);
79-
debug!(
80-
"Cache-control header: {:?}",
81-
&response.http_data.cache_control
82-
);
8385
}
8486
}
8587
}

icann-rdap-cli/tests/integration/queries.rs

+18
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,21 @@ async fn GIVEN_idn_WHEN_query_a_label_THEN_success() {
175175
let assert = test_jig.cmd.assert();
176176
assert.success();
177177
}
178+
179+
#[tokio::test(flavor = "multi_thread")]
180+
async fn GIVEN_domain_WHEN_search_domain_names_THEN_success() {
181+
// GIVEN
182+
let mut test_jig = TestJig::new_with_enable_domain_name_search().await;
183+
let mut tx = test_jig.mem.new_tx().await.expect("new transaction");
184+
tx.add_domain(&Domain::basic().ldh_name("foo.example").build())
185+
.await
186+
.expect("add domain in tx");
187+
tx.commit().await.expect("tx commit");
188+
189+
// WHEN
190+
test_jig.cmd.arg("-t").arg("domain-name").arg("foo.*");
191+
192+
// THEN
193+
let assert = test_jig.cmd.assert();
194+
assert.success();
195+
}

icann-rdap-cli/tests/integration/test_jig.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use assert_cmd::Command;
22
use icann_rdap_srv::config::ListenConfig;
33
use icann_rdap_srv::server::AppState;
44
use icann_rdap_srv::server::Listener;
5+
use icann_rdap_srv::storage::mem::config::MemConfig;
56
use icann_rdap_srv::storage::mem::ops::Mem;
7+
use icann_rdap_srv::storage::CommonConfig;
68
use std::time::Duration;
79
use test_dir::DirBuilder;
810
use test_dir::FileType;
@@ -18,7 +20,19 @@ pub struct TestJig {
1820

1921
impl TestJig {
2022
pub async fn new() -> TestJig {
21-
let mem = Mem::default();
23+
let common_config = CommonConfig::default();
24+
TestJig::new_common_config(common_config).await
25+
}
26+
27+
pub async fn new_with_enable_domain_name_search() -> TestJig {
28+
let common_config = CommonConfig::builder()
29+
.domain_search_by_name_enable(true)
30+
.build();
31+
TestJig::new_common_config(common_config).await
32+
}
33+
34+
pub async fn new_common_config(common_config: CommonConfig) -> TestJig {
35+
let mem = Mem::new(MemConfig::builder().common_config(common_config).build());
2236
let app_state = AppState {
2337
storage: mem.clone(),
2438
bootstrap: false,

icann-rdap-client/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ An RDAP client library.
1010

1111
[dependencies]
1212

13-
icann-rdap-common = { version = "0.0.17", path = "../icann-rdap-common" }
13+
icann-rdap-common = { version = "0.0.18", path = "../icann-rdap-common" }
1414

1515
buildstructor.workspace = true
1616
cidr-utils.workspace = true

0 commit comments

Comments
 (0)