From f34aec8b567711a764138183ddc6af0352e30c82 Mon Sep 17 00:00:00 2001 From: gbrodman Date: Tue, 8 Jul 2025 10:54:07 -0400 Subject: [PATCH] Add an "about" link to registrars in RDAP (#2771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the response profile: 2.4.6. Registrar URL - The entity with the registrar role in the RDAP response MUST contain a links member [RFC9083]. The links object MUST contain the elements: value, identical to the the RDAP Base URL for the Registrar as provided in the IANA “Registrar IDs” registry (i.e., https://www.iana.org/assignments/registrar-ids); rel:about, and href containing the Registrar URL. Note: in cases where the Registry Operator acts as sponsoring Registrar (e.g., IANA Registrar ID 9999), the href shall contain a URL from the Registry. --- .../registry/rdap/RdapJsonFormatter.java | 9 ++++++ .../UpdateRegistrarRdapBaseUrlsAction.java | 31 +++++++++++++------ .../JpaTransactionManagerExtension.java | 2 ++ .../testing/FullFieldsTestEntityHelper.java | 4 +-- .../google/registry/rdap/rdap_domain.json | 12 +++---- .../rdap/rdap_domain_add_grace_period.json | 12 +++++++ .../rdap_domain_auto_renew_grace_period.json | 12 +++++++ .../registry/rdap/rdap_domain_cat2.json | 12 +++---- .../registry/rdap/rdap_domain_deleted.json | 12 +++---- ...ap_domain_explicit_renew_grace_period.json | 12 +++++++ ..._domain_no_contacts_exist_with_remark.json | 12 +++---- ...rdap_domain_no_registrant_with_remark.json | 12 +++---- ...ending_delete_redemption_grace_period.json | 12 +++++++ ..._domain_redacted_contacts_with_remark.json | 12 +++---- .../rdap_domain_transfer_grace_period.json | 12 +++++++ .../registry/rdap/rdap_domain_unicode.json | 12 +++---- ...omain_unicode_no_contacts_with_remark.json | 12 +++---- .../google/registry/rdap/rdap_host.json | 6 ++++ .../registry/rdap/rdap_host_external.json | 6 ++++ .../registry/rdap/rdap_host_linked.json | 6 ++++ .../registry/rdap/rdap_host_unicode.json | 6 ++++ .../rdap/rdap_nontruncated_registrars.json | 24 ++++++++++++++ .../google/registry/rdap/rdap_registrar.json | 6 ++++ .../registry/rdap/rdap_registrar_test.json | 8 +++++ .../rdap/rdap_truncated_mixed_entities.json | 10 ++++-- .../rdap/rdap_truncated_registrars.json | 24 ++++++++++++++ .../registry/rdap/rdapjson_domain_full.json | 11 ++++--- .../rdap/rdapjson_domain_logged_out.json | 11 ++++--- .../rdap/rdapjson_domain_no_nameservers.json | 11 ++++--- .../registry/rdap/rdapjson_host_both.json | 6 ++++ .../registry/rdap/rdapjson_host_ipv4.json | 6 ++++ .../registry/rdap/rdapjson_host_ipv6.json | 6 ++++ .../rdap/rdapjson_host_no_addresses.json | 6 ++++ .../rdap/rdapjson_host_not_linked.json | 6 ++++ .../rdap/rdapjson_host_pending_transfer.json | 6 ++++ .../registry/rdap/rdapjson_registrar.json | 6 ++++ .../rdap/rdapjson_registrar_summary.json | 6 ++++ 37 files changed, 302 insertions(+), 77 deletions(-) diff --git a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java index 04a7c4b78..192463827 100644 --- a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java +++ b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java @@ -721,6 +721,15 @@ public class RdapJsonFormatter { builder.linksBuilder().add(makeSelfLink("entity", ianaIdentifier.toString())); } + // RDAP Response Profile 2.4.6: must have a links entry pointing to the registrar URL, with a + // rel:about and a value containing the registrar RDAP base URL (if present) + if (registrar.getUrl() != null) { + Link.Builder registrarLinkBuilder = + Link.builder().setHref(registrar.getUrl()).setRel("about").setType("text/html"); + registrar.getRdapBaseUrls().stream().findFirst().ifPresent(registrarLinkBuilder::setValue); + builder.linksBuilder().add(registrarLinkBuilder.build()); + } + // There's no mention of the registrar STATUS in the RDAP Response Profile, so we'll only add it // for FULL response // We could probably not add it at all, but it could be useful for us internally diff --git a/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java b/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java index 45fb25798..09becfe7d 100644 --- a/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java +++ b/core/src/main/java/google/registry/rdap/UpdateRegistrarRdapBaseUrlsAction.java @@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.flogger.FluentLogger; import google.registry.model.registrar.Registrar; +import google.registry.persistence.PersistenceModule; import google.registry.request.Action; import google.registry.request.Action.GaeService; import google.registry.request.HttpException.InternalServerErrorException; @@ -36,7 +37,7 @@ import jakarta.inject.Inject; import java.io.IOException; import java.io.StringReader; import java.net.HttpURLConnection; -import java.net.URL; +import java.net.URI; import java.security.GeneralSecurityException; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; @@ -72,7 +73,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable { public void run() { try { ImmutableMap ianaIdsToUrls = getIanaIdsToUrls(); - tm().transact(() -> processAllRegistrars(ianaIdsToUrls)); + processAllRegistrars(ianaIdsToUrls); } catch (Exception e) { throw new InternalServerErrorException("Error when retrieving RDAP base URL CSV file", e); } @@ -80,7 +81,14 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable { private static void processAllRegistrars(ImmutableMap ianaIdsToUrls) { int nonUpdatedRegistrars = 0; - for (Registrar registrar : Registrar.loadAll()) { + // Split into multiple transactions to avoid load-save-reload conflicts. Re-building a registrar + // requires a full (cached) load of all registrars to avoid IANA ID conflicts, so if multiple + // registrars are modified in the same transaction, the second build call will fail. + Iterable registrars = + tm().transact( + PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ, + Registrar::loadAll); + for (Registrar registrar : registrars) { // Only update REAL registrars if (registrar.getType() != Registrar.Type.REAL) { continue; @@ -100,7 +108,12 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable { "Updating RDAP base URLs for registrar %s from %s to %s", registrar.getRegistrarId(), registrar.getRdapBaseUrls(), baseUrls); } - tm().put(registrar.asBuilder().setRdapBaseUrls(baseUrls).build()); + tm().transact( + () -> { + // Reload inside a transaction to avoid race conditions + Registrar reloadedRegistrar = tm().loadByEntity(registrar); + tm().put(reloadedRegistrar.asBuilder().setRdapBaseUrls(baseUrls).build()); + }); } } logger.atInfo().log("No change in RDAP base URLs for %d registrars", nonUpdatedRegistrars); @@ -108,9 +121,9 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable { private ImmutableMap getIanaIdsToUrls() throws IOException, GeneralSecurityException { - CSVParser csv; - HttpURLConnection connection = urlConnectionService.createConnection(new URL(RDAP_IDS_URL)); - // Explictly set the accepted encoding, as we know Brotli causes us problems when talking to + HttpURLConnection connection = + urlConnectionService.createConnection(URI.create(RDAP_IDS_URL).toURL()); + // Explicitly set the accepted encoding, as we know Brotli causes us problems when talking to // ICANN. connection.setRequestProperty(ACCEPT_ENCODING, "gzip"); String csvString; @@ -128,11 +141,11 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable { } finally { connection.disconnect(); } - csv = + CSVParser csv = CSVFormat.Builder.create(CSVFormat.DEFAULT) .setHeader() .setSkipHeaderRecord(true) - .build() + .get() .parse(new StringReader(csvString)); ImmutableMap.Builder result = new ImmutableMap.Builder<>(); for (CSVRecord record : csv) { diff --git a/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerExtension.java b/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerExtension.java index 8150f02b2..47c7f3e01 100644 --- a/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerExtension.java +++ b/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerExtension.java @@ -379,6 +379,7 @@ public abstract class JpaTransactionManagerExtension .setPassword("foo-BAR2") .setPhoneNumber("+1.3334445555") .setPhonePasscode("12345") + .setRdapBaseUrls(ImmutableSet.of("https://rdap.newregistrar.com/")) .setRegistryLockAllowed(false) .build(); } @@ -393,6 +394,7 @@ public abstract class JpaTransactionManagerExtension .setPassword("password2") .setPhoneNumber("+1.2223334444") .setPhonePasscode("22222") + .setRdapBaseUrls(ImmutableSet.of("https://rdap.theregistrar.com/")) .setRegistryLockAllowed(true) .build(); } diff --git a/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java b/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java index 79665863b..88f04bf18 100644 --- a/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java +++ b/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java @@ -84,9 +84,7 @@ public final class FullFieldsTestEntityHelper { .setFaxNumber("+1.2125551213") .setEmailAddress("contact-us@example.com") .setWhoisServer("whois.example.com") - .setRdapBaseUrls( - ImmutableSet.of( - "https://rdap.example.com/withSlash/", "https://rdap.example.com/withoutSlash")) + .setRdapBaseUrls(ImmutableSet.of("https://rdap.example.com/withSlash/")) .setUrl("http://my.fake.url") .build(); } diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain.json b/core/src/test/resources/google/registry/rdap/rdap_domain.json index cf2fb5e53..d87dcef4e 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain.json @@ -25,12 +25,6 @@ "type": "application/rdap+json", "rel": "related", "value": "%REQUEST_URL%" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "%REQUEST_URL%" } ], "events": [ @@ -122,6 +116,12 @@ "type": "application/rdap+json", "rel": "self", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "vcardArray" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_add_grace_period.json b/core/src/test/resources/google/registry/rdap/rdap_domain_add_grace_period.json index 24e67783c..7e5fc2985 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_add_grace_period.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_add_grace_period.json @@ -15,6 +15,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/addgraceperiod.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds": [ @@ -128,6 +134,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/addgraceperiod.lol" + }, + { + "href": "https://rdap.theregistrar.com/domain/addgraceperiod.lol", + "rel": "related", + "type": "application/rdap+json", + "value": "https://example.tld/rdap/domain/addgraceperiod.lol" } ], "nameservers": [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_auto_renew_grace_period.json b/core/src/test/resources/google/registry/rdap/rdap_domain_auto_renew_grace_period.json index acc69a3b2..b40eadaf3 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_auto_renew_grace_period.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_auto_renew_grace_period.json @@ -15,6 +15,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/autorenew.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds": [ @@ -132,6 +138,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/autorenew.lol" + }, + { + "href": "https://rdap.theregistrar.com/domain/autorenew.lol", + "rel": "related", + "type": "application/rdap+json", + "value": "https://example.tld/rdap/domain/autorenew.lol" } ], "nameservers": [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_cat2.json b/core/src/test/resources/google/registry/rdap/rdap_domain_cat2.json index 028397d14..ef36ea7d8 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_cat2.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_cat2.json @@ -25,12 +25,6 @@ "type": "application/rdap+json", "rel": "related", "value": "https://example.tld/rdap/domains" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "https://example.tld/rdap/domains" } ], "events": [ @@ -105,6 +99,12 @@ "type": "application/rdap+json", "rel": "self", "value": "https://example.tld/rdap/domains" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "vcardArray" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_deleted.json b/core/src/test/resources/google/registry/rdap/rdap_domain_deleted.json index 65c0a615c..3aee16abe 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_deleted.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_deleted.json @@ -26,12 +26,6 @@ "type": "application/rdap+json", "rel": "related", "value": "%REQUEST_URL%" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "%REQUEST_URL%" } ], "events": [ @@ -117,6 +111,12 @@ "type": "application/rdap+json", "rel": "self", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "vcardArray" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_explicit_renew_grace_period.json b/core/src/test/resources/google/registry/rdap/rdap_domain_explicit_renew_grace_period.json index 902bcc4ff..a05832925 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_explicit_renew_grace_period.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_explicit_renew_grace_period.json @@ -15,6 +15,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/renew.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds": [ @@ -128,6 +134,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/renew.lol" + }, + { + "href": "https://rdap.theregistrar.com/domain/renew.lol", + "rel": "related", + "type": "application/rdap+json", + "value": "https://example.tld/rdap/domain/renew.lol" } ], "nameservers": [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_no_contacts_exist_with_remark.json b/core/src/test/resources/google/registry/rdap/rdap_domain_no_contacts_exist_with_remark.json index e17f2ee0e..0fdbba138 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_no_contacts_exist_with_remark.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_no_contacts_exist_with_remark.json @@ -25,12 +25,6 @@ "type": "application/rdap+json", "rel": "related", "value": "https://example.tld/rdap/domain/cat.lol" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "https://example.tld/rdap/domain/cat.lol" } ], "events": [ @@ -112,6 +106,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "https://example.tld/rdap/domain/cat.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_no_registrant_with_remark.json b/core/src/test/resources/google/registry/rdap/rdap_domain_no_registrant_with_remark.json index 38d2ae2c6..77a7c91ac 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_no_registrant_with_remark.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_no_registrant_with_remark.json @@ -25,12 +25,6 @@ "type": "application/rdap+json", "rel": "related", "value": "https://example.tld/rdap/domain/cat.lol" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "https://example.tld/rdap/domain/cat.lol" } ], "events": [ @@ -112,6 +106,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "https://example.tld/rdap/domain/cat.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_pending_delete_redemption_grace_period.json b/core/src/test/resources/google/registry/rdap/rdap_domain_pending_delete_redemption_grace_period.json index 5adcbfef2..a0ba8ebba 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_pending_delete_redemption_grace_period.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_pending_delete_redemption_grace_period.json @@ -15,6 +15,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/redemption.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds": [ @@ -128,6 +134,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/redemption.lol" + }, + { + "href": "https://rdap.theregistrar.com/domain/redemption.lol", + "rel": "related", + "type": "application/rdap+json", + "value": "https://example.tld/rdap/domain/redemption.lol" } ], "nameservers": [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_redacted_contacts_with_remark.json b/core/src/test/resources/google/registry/rdap/rdap_domain_redacted_contacts_with_remark.json index effea91f6..7f5effd65 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_redacted_contacts_with_remark.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_redacted_contacts_with_remark.json @@ -25,12 +25,6 @@ "type": "application/rdap+json", "rel": "related", "value": "%REQUEST_URL%" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "%REQUEST_URL%" } ], "events": [ @@ -112,6 +106,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_transfer_grace_period.json b/core/src/test/resources/google/registry/rdap/rdap_domain_transfer_grace_period.json index e0c5c1d72..3fa17a91b 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_transfer_grace_period.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_transfer_grace_period.json @@ -15,6 +15,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/transfer.lol" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds": [ @@ -128,6 +134,12 @@ "rel": "self", "type": "application/rdap+json", "value": "https://example.tld/rdap/domain/transfer.lol" + }, + { + "href": "https://rdap.theregistrar.com/domain/transfer.lol", + "rel": "related", + "type": "application/rdap+json", + "value": "https://example.tld/rdap/domain/transfer.lol" } ], "nameservers": [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_unicode.json b/core/src/test/resources/google/registry/rdap/rdap_domain_unicode.json index 3ec123cd5..942665b00 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_unicode.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_unicode.json @@ -26,12 +26,6 @@ "type": "application/rdap+json", "rel": "related", "value": "%REQUEST_URL%" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "%REQUEST_URL%" } ], "events": [ @@ -115,6 +109,12 @@ "type": "application/rdap+json", "rel": "self", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "vcardArray" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_domain_unicode_no_contacts_with_remark.json b/core/src/test/resources/google/registry/rdap/rdap_domain_unicode_no_contacts_with_remark.json index 29a1beda2..9e741aeca 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_domain_unicode_no_contacts_with_remark.json +++ b/core/src/test/resources/google/registry/rdap/rdap_domain_unicode_no_contacts_with_remark.json @@ -26,12 +26,6 @@ "type": "application/rdap+json", "rel": "related", "value": "https://example.tld/rdap/domains" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%", - "type": "application/rdap+json", - "rel": "related", - "value": "https://example.tld/rdap/domains" } ], "events": [ @@ -115,6 +109,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "https://example.tld/rdap/domains" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_host.json b/core/src/test/resources/google/registry/rdap/rdap_host.json index b18a661b1..6e1bd22ed 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_host.json +++ b/core/src/test/resources/google/registry/rdap/rdap_host.json @@ -39,6 +39,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdap_host_external.json b/core/src/test/resources/google/registry/rdap/rdap_host_external.json index 3927b6d39..1b49074c4 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_host_external.json +++ b/core/src/test/resources/google/registry/rdap/rdap_host_external.json @@ -36,6 +36,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdap_host_linked.json b/core/src/test/resources/google/registry/rdap/rdap_host_linked.json index 1b4b72ecb..14bc390c6 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_host_linked.json +++ b/core/src/test/resources/google/registry/rdap/rdap_host_linked.json @@ -42,6 +42,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdap_host_unicode.json b/core/src/test/resources/google/registry/rdap/rdap_host_unicode.json index b2a86dde4..849f7484c 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_host_unicode.json +++ b/core/src/test/resources/google/registry/rdap/rdap_host_unicode.json @@ -40,6 +40,12 @@ "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.theregistrar.com/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdap_nontruncated_registrars.json b/core/src/test/resources/google/registry/rdap/rdap_nontruncated_registrars.json index ce7a13132..7b7702ba7 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_nontruncated_registrars.json +++ b/core/src/test/resources/google/registry/rdap/rdap_nontruncated_registrars.json @@ -11,6 +11,12 @@ "href": "https://example.tld/rdap/entity/301", "type": "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": @@ -69,6 +75,12 @@ "href": "https://example.tld/rdap/entity/302", "type": "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": @@ -127,6 +139,12 @@ "href": "https://example.tld/rdap/entity/303", "type": "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": @@ -185,6 +203,12 @@ "href": "https://example.tld/rdap/entity/304", "type": "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": diff --git a/core/src/test/resources/google/registry/rdap/rdap_registrar.json b/core/src/test/resources/google/registry/rdap/rdap_registrar.json index ded83bbc3..7b76e5cd9 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_registrar.json +++ b/core/src/test/resources/google/registry/rdap/rdap_registrar.json @@ -15,6 +15,12 @@ "href": "https://example.tld/rdap/entity/%REGISTRAR_HANDLE_1%", "type" : "application/rdap+json", "value": "%REQUEST_URL%" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdap_registrar_test.json b/core/src/test/resources/google/registry/rdap/rdap_registrar_test.json index bc05890da..e8a9803c0 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_registrar_test.json +++ b/core/src/test/resources/google/registry/rdap/rdap_registrar_test.json @@ -6,6 +6,14 @@ ], "objectClassName" : "entity", "handle" : "%REGISTRAR_HANDLE_1%", + "links" : [ + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" + } + ], "status" : ["%STATUS_1%"], "roles" : ["registrar"], "events": [ diff --git a/core/src/test/resources/google/registry/rdap/rdap_truncated_mixed_entities.json b/core/src/test/resources/google/registry/rdap/rdap_truncated_mixed_entities.json index 59f9622c6..a683b2e30 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_truncated_mixed_entities.json +++ b/core/src/test/resources/google/registry/rdap/rdap_truncated_mixed_entities.json @@ -64,9 +64,9 @@ "links" : [ { - "rel" : "self", + "rel": "self", "href": "https://example.tld/rdap/entity/0002-ROID", - "type" : "application/rdap+json", + "type": "application/rdap+json", "value": "https://example.tld/rdap/entities" } ], @@ -182,6 +182,12 @@ "href": "https://example.tld/rdap/entity/301", "type" : "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdap_truncated_registrars.json b/core/src/test/resources/google/registry/rdap/rdap_truncated_registrars.json index d7a817222..9180217ad 100644 --- a/core/src/test/resources/google/registry/rdap/rdap_truncated_registrars.json +++ b/core/src/test/resources/google/registry/rdap/rdap_truncated_registrars.json @@ -11,6 +11,12 @@ "href": "https://example.tld/rdap/entity/301", "type" : "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : @@ -69,6 +75,12 @@ "href": "https://example.tld/rdap/entity/302", "type" : "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : @@ -127,6 +139,12 @@ "href": "https://example.tld/rdap/entity/303", "type" : "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : @@ -185,6 +203,12 @@ "href": "https://example.tld/rdap/entity/304", "type" : "application/rdap+json", "value": "https://example.tld/rdap/entities" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_domain_full.json b/core/src/test/resources/google/registry/rdap/rdapjson_domain_full.json index 9fdc0d4ff..816e0ad48 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_domain_full.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_domain_full.json @@ -21,11 +21,6 @@ "rel" : "related", "href" : "https://rdap.example.com/withSlash/domain/cat.xn--q9jyb4c", "type" : "application/rdap+json" - }, - { - "rel" : "related", - "href" : "https://rdap.example.com/withoutSlash/domain/cat.xn--q9jyb4c", - "type" : "application/rdap+json" } ], "events": [ @@ -112,6 +107,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_domain_logged_out.json b/core/src/test/resources/google/registry/rdap/rdapjson_domain_logged_out.json index 32c8f89f0..870e40032 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_domain_logged_out.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_domain_logged_out.json @@ -21,11 +21,6 @@ "href": "https://rdap.example.com/withSlash/domain/cat.xn--q9jyb4c", "type": "application/rdap+json", "rel": "related" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/cat.xn--q9jyb4c", - "type": "application/rdap+json", - "rel": "related" } ], "events": [ @@ -109,6 +104,12 @@ "rel": "self", "href": "https://example.tld/rdap/entity/1", "type": "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": [ diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_domain_no_nameservers.json b/core/src/test/resources/google/registry/rdap/rdapjson_domain_no_nameservers.json index 6671db900..a5847f99d 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_domain_no_nameservers.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_domain_no_nameservers.json @@ -22,11 +22,6 @@ "href": "https://rdap.example.com/withSlash/domain/fish.xn--q9jyb4c", "type": "application/rdap+json", "rel": "related" - }, - { - "href": "https://rdap.example.com/withoutSlash/domain/fish.xn--q9jyb4c", - "type": "application/rdap+json", - "rel": "related" } ], "events": [ @@ -60,6 +55,12 @@ "rel": "self", "href": "https://example.tld/rdap/entity/1", "type": "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_host_both.json b/core/src/test/resources/google/registry/rdap/rdapjson_host_both.json index d8de31c41..45e303818 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_host_both.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_host_both.json @@ -34,6 +34,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv4.json b/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv4.json index 6aee80392..be1d7f3e3 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv4.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv4.json @@ -30,6 +30,12 @@ "rel": "self", "href": "https://example.tld/rdap/entity/1", "type": "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv6.json b/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv6.json index 2ae72a0bb..685f8052b 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv6.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_host_ipv6.json @@ -30,6 +30,12 @@ "rel": "self", "href": "https://example.tld/rdap/entity/1", "type": "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds": diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_host_no_addresses.json b/core/src/test/resources/google/registry/rdap/rdapjson_host_no_addresses.json index 982f722ca..a5513fb06 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_host_no_addresses.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_host_no_addresses.json @@ -29,6 +29,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_host_not_linked.json b/core/src/test/resources/google/registry/rdap/rdapjson_host_not_linked.json index 4c4695fc5..545609f4d 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_host_not_linked.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_host_not_linked.json @@ -29,6 +29,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_host_pending_transfer.json b/core/src/test/resources/google/registry/rdap/rdapjson_host_pending_transfer.json index 71ca53e23..a4af8e86f 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_host_pending_transfer.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_host_pending_transfer.json @@ -29,6 +29,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "publicIds" : diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_registrar.json b/core/src/test/resources/google/registry/rdap/rdapjson_registrar.json index 8fce23a0e..4d063d3dc 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_registrar.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_registrar.json @@ -9,6 +9,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "events": [ diff --git a/core/src/test/resources/google/registry/rdap/rdapjson_registrar_summary.json b/core/src/test/resources/google/registry/rdap/rdapjson_registrar_summary.json index 7bf71b568..a06f68e7e 100644 --- a/core/src/test/resources/google/registry/rdap/rdapjson_registrar_summary.json +++ b/core/src/test/resources/google/registry/rdap/rdapjson_registrar_summary.json @@ -8,6 +8,12 @@ "rel" : "self", "href" : "https://example.tld/rdap/entity/1", "type" : "application/rdap+json" + }, + { + "rel": "about", + "href": "http://my.fake.url", + "type": "text/html", + "value": "https://rdap.example.com/withSlash/" } ], "events": [