1
0
mirror of https://github.com/google/nomulus synced 2026-01-06 13:36:48 +00:00

Add an "about" link to registrars in RDAP (#2771)

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.
This commit is contained in:
gbrodman
2025-07-08 10:54:07 -04:00
committed by GitHub
parent b27b077638
commit f34aec8b56
37 changed files with 302 additions and 77 deletions

View File

@@ -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

View File

@@ -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<String, String> 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<String, String> 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<Registrar> 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<String, String> 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<String, String> result = new ImmutableMap.Builder<>();
for (CSVRecord record : csv) {

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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" : [

View File

@@ -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": [

View File

@@ -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": [

View File

@@ -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" : [

View File

@@ -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" : [

View File

@@ -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": [

View File

@@ -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" : [

View File

@@ -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" : [

View File

@@ -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": [

View File

@@ -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" : [

View File

@@ -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": [

View File

@@ -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" : [

View File

@@ -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" : [

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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":

View File

@@ -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" :

View File

@@ -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": [

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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": [

View File

@@ -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":

View File

@@ -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" :

View File

@@ -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":

View File

@@ -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":

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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" :

View File

@@ -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": [

View File

@@ -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": [