RDAP: Display summary data for search result items

It appears to be standard RDAP practice when returning result sets for domain, nameserver and entity searches to give only summary data for each result item. Any information that can be gleaned from the object itself is included, but related resources are not included. For a domain, for instance, the domain information is included, but nameservers, entities and events (which come from history entries) are suppressed. In their place, there is a standard boilerplate remark in the object indicating that only summary data is included, and that the user should query the item directly to get the full data. Note that summary data is used only for searches; direct queries for an item will still return full data.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=133973835
This commit is contained in:
mountford 2016-09-22 11:00:37 -07:00 committed by Ben McIlwain
parent 740d49e22e
commit b5e421cee3
25 changed files with 773 additions and 1120 deletions

View file

@ -21,10 +21,10 @@ import static google.registry.request.Action.Method.HEAD;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.TestDataHelper.loadFileWithSubstitutions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import google.registry.model.ofy.Ofy;
import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
import google.registry.request.HttpException;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
@ -55,7 +55,7 @@ public class RdapActionBaseTest {
/**
* Dummy RdapActionBase subclass used for testing.
*/
class RdapTestAction extends RdapActionBase {
static class RdapTestAction extends RdapActionBase {
public static final String PATH = "/rdap/test/";
@ -71,7 +71,7 @@ public class RdapActionBaseTest {
@Override
public ImmutableMap<String, Object> getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest, String linkBase) throws HttpException {
String pathSearchString, boolean isHeadRequest, String linkBase) {
if (pathSearchString.equals("IllegalArgumentException")) {
throw new IllegalArgumentException();
}
@ -83,7 +83,8 @@ public class RdapActionBaseTest {
RdapJsonFormatter.addTopLevelEntries(
builder,
BoilerplateType.OTHER,
null,
ImmutableList.of(),
ImmutableList.of(),
"http://myserver.google.com/");
return builder.build();
}

View file

@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistDomainAsDeleted;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.DatastoreHelper.persistResources;
import static google.registry.testing.DatastoreHelper.persistSimpleResources;
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistContactResource;
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistHostResource;
@ -110,7 +111,7 @@ public class RdapDomainSearchActionTest {
action.nsIpParam = Optional.absent();
break;
}
action.rdapResultSetMaxSize = 5;
action.rdapResultSetMaxSize = 4;
action.run();
return JSONValue.parse(response.getPayload());
}
@ -518,20 +519,21 @@ public class RdapDomainSearchActionTest {
}
private void createManyDomains(int numActiveDomains, int numTotalDomainsPerActiveDomain) {
// Create all the domains at once, then persist them in parallel, for increased efficiency.
ImmutableList.Builder<DomainResource> domainsBuilder = new ImmutableList.Builder<>();
for (int i = 1; i <= numActiveDomains * numTotalDomainsPerActiveDomain; i++) {
String domainName = String.format("domain%d.lol", i);
DomainResource domain =
DomainResource.Builder builder =
makeDomainResource(
domainName, contact1, contact2, contact3, hostNs1CatLol, hostNs2CatLol, registrar)
.asBuilder()
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
.build();
if (i % numTotalDomainsPerActiveDomain == 0) {
persistResource(domain);
} else {
persistDomainAsDeleted(domain, clock.nowUtc());
.setCreationTimeForTest(clock.nowUtc().minusYears(3));
if (i % numTotalDomainsPerActiveDomain != 0) {
builder = builder.setDeletionTime(clock.nowUtc().minusDays(1));
}
domainsBuilder.add(builder.build());
}
persistResources(domainsBuilder.build());
}
private void checkNumberOfDomainsInResult(Object obj, int expected) {
@ -549,10 +551,10 @@ public class RdapDomainSearchActionTest {
@Test
public void testDomainMatch_manyDeletedDomains_fullResultSet() throws Exception {
// There are enough domains to fill a full result set; deleted domains are ignored.
createManyDomains(5, 4);
createManyDomains(4, 4);
Object obj = generateActualJson(RequestType.NAME, "domain*.lol");
assertThat(response.getStatus()).isEqualTo(200);
checkNumberOfDomainsInResult(obj, 5);
checkNumberOfDomainsInResult(obj, 4);
}
@Test
@ -571,7 +573,7 @@ public class RdapDomainSearchActionTest {
// This is not exactly desired behavior, but expected: There are enough domains to fill a full
// result set, but there are so many deleted domains that we run out of patience before we work
// our way through all of them.
createManyDomains(5, 150);
createManyDomains(4, 150);
Object obj = generateActualJson(RequestType.NAME, "domain*.lol");
assertThat(response.getStatus()).isEqualTo(200);
checkNumberOfDomainsInResult(obj, 3);
@ -587,7 +589,8 @@ public class RdapDomainSearchActionTest {
@Test
public void testNameserverMatchWithWildcard_found() throws Exception {
assertThat(generateActualJson(RequestType.NS_LDH_NAME, "ns2.cat.l*"))
.isEqualTo(generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
.isEqualTo(
generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
assertThat(response.getStatus()).isEqualTo(200);
}
@ -672,7 +675,8 @@ public class RdapDomainSearchActionTest {
public void testNameserverMatchOneDeletedDomain_foundTheOther() throws Exception {
persistDomainAsDeleted(domainCatExample, clock.nowUtc());
assertThat(generateActualJson(RequestType.NS_LDH_NAME, "ns1.cat.lol"))
.isEqualTo(generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
.isEqualTo(
generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
assertThat(response.getStatus()).isEqualTo(200);
}
@ -748,7 +752,8 @@ public class RdapDomainSearchActionTest {
public void testAddressMatchOneDeletedDomain_foundTheOther() throws Exception {
persistDomainAsDeleted(domainCatExample, clock.nowUtc());
assertThat(generateActualJson(RequestType.NS_IP, "1.2.3.4"))
.isEqualTo(generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
.isEqualTo(
generateExpectedJsonForDomain("cat.lol", null, "C-LOL", "rdap_domain.json"));
assertThat(response.getStatus()).isEqualTo(200);
}

View file

@ -41,6 +41,7 @@ import google.registry.model.registrar.RegistrarContact;
import google.registry.model.registry.Registry.TldState;
import google.registry.model.reporting.HistoryEntry;
import google.registry.rdap.RdapJsonFormatter.MakeRdapJsonNoticeParameters;
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
import google.registry.testing.InjectRule;
@ -204,35 +205,59 @@ public class RdapJsonFormatterTest {
@Test
public void testRegistrar() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForRegistrar(
registrar, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
registrar, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_registrar.json"));
}
@Test
public void testRegistrar_summary() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForRegistrar(
registrar, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.SUMMARY))
.isEqualTo(loadJson("rdapjson_registrar_summary.json"));
}
@Test
public void testHost_ipv4() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
hostResourceIpv4, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
hostResourceIpv4, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_host_ipv4.json"));
}
@Test
public void testHost_ipv6() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
hostResourceIpv6, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
hostResourceIpv6, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_host_ipv6.json"));
}
@Test
public void testHost_both() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
hostResourceBoth, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
hostResourceBoth, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc(), OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_host_both.json"));
}
@Test
public void testHost_both_summary() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
hostResourceBoth,
false,
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.SUMMARY))
.isEqualTo(loadJson("rdapjson_host_both_summary.json"));
}
@Test
public void testHost_noAddresses() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForHost(
hostResourceNoAddresses, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
hostResourceNoAddresses,
false,
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_host_no_addresses.json"));
}
@ -245,10 +270,25 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc()))
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_registrant.json"));
}
@Test
public void testRegistrant_summary() throws Exception {
assertThat(
RdapJsonFormatter.makeRdapJsonForContact(
contactResourceRegistrant,
false,
Optional.of(DesignatedContact.Type.REGISTRANT),
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.SUMMARY))
.isEqualTo(loadJson("rdapjson_registrant_summary.json"));
}
@Test
public void testRegistrant_baseHasNoTrailingSlash() throws Exception {
assertThat(
@ -258,7 +298,8 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
LINK_BASE_NO_TRAILING_SLASH,
WHOIS_SERVER,
clock.nowUtc()))
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_registrant.json"));
}
@ -271,7 +312,8 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
null,
WHOIS_SERVER,
clock.nowUtc()))
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_registrant_nobase.json"));
}
@ -284,7 +326,8 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.ADMIN),
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc()))
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_admincontact.json"));
}
@ -297,7 +340,8 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.TECH),
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc()))
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_techcontact.json"));
}
@ -310,21 +354,44 @@ public class RdapJsonFormatterTest {
Optional.<DesignatedContact.Type>absent(),
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc()))
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_rolelesscontact.json"));
}
@Test
public void testDomain_full() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
domainResourceFull, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
domainResourceFull,
false,
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_domain_full.json"));
}
@Test
public void testDomain_summary() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
domainResourceFull,
false,
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.SUMMARY))
.isEqualTo(loadJson("rdapjson_domain_summary.json"));
}
@Test
public void testDomain_noNameservers() throws Exception {
assertThat(RdapJsonFormatter.makeRdapJsonForDomain(
domainResourceNoNameservers, false, LINK_BASE, WHOIS_SERVER, clock.nowUtc()))
domainResourceNoNameservers,
false,
LINK_BASE,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL))
.isEqualTo(loadJson("rdapjson_domain_no_nameservers.json"));
}
@ -406,7 +473,8 @@ public class RdapJsonFormatterTest {
RdapJsonFormatter.addTopLevelEntries(
builder,
RdapJsonFormatter.BoilerplateType.OTHER,
null,
ImmutableList.of(),
ImmutableList.of(),
LINK_BASE);
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel.json"));
}
@ -419,6 +487,7 @@ public class RdapJsonFormatterTest {
builder,
RdapJsonFormatter.BoilerplateType.OTHER,
ImmutableList.of(RdapHelpAction.getJsonHelpNotice("/tos", LINK_BASE)),
ImmutableList.of(),
LINK_BASE);
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel.json"));
}
@ -430,7 +499,8 @@ public class RdapJsonFormatterTest {
RdapJsonFormatter.addTopLevelEntries(
builder,
RdapJsonFormatter.BoilerplateType.DOMAIN,
null,
ImmutableList.of(),
ImmutableList.of(),
LINK_BASE);
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel_domain.json"));
}
@ -443,6 +513,7 @@ public class RdapJsonFormatterTest {
builder,
RdapJsonFormatter.BoilerplateType.DOMAIN,
ImmutableList.of(RdapHelpAction.getJsonHelpNotice("/tos", LINK_BASE)),
ImmutableList.of(),
LINK_BASE);
assertThat(builder.build()).isEqualTo(loadJson("rdapjson_toplevel_domain.json"));
}

View file

@ -382,7 +382,12 @@ public class RdapNameserverSearchActionTest {
assertThat(generateActualJsonWithIp("bad:f00d:cafe::15:beef"))
.isEqualTo(
generateExpectedJsonForNameserver(
"ns2.cat.lol", null, "4-ROID", "v6", "bad:f00d:cafe::15:beef", "rdap_host.json"));
"ns2.cat.lol",
null,
"4-ROID",
"v6",
"bad:f00d:cafe::15:beef",
"rdap_host.json"));
assertThat(response.getStatus()).isEqualTo(200);
}
}

View file

@ -14,15 +14,13 @@
"type" : "application/rdap+json"
}
],
"events": [
"remarks": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
],
"vcardArray" :
@ -63,15 +61,13 @@
"type" : "application/rdap+json"
}
],
"events": [
"remarks": [
{
"eventAction": "registration",
"eventActor": "2-Registrar",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
],
"publicIds" :
@ -102,41 +98,6 @@
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
["email", {}, "text", "contact-us@example.com"]
]
],
"entities" :
[
{
"objectClassName" : "entity",
"status" : ["active"],
"roles" : ["administrative"],
"vcardArray" :
[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "Jane Doe"],
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2125551215"],
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551216"],
["email", {}, "text", "janedoe@example.com"]
]
],
},
{
"objectClassName" : "entity",
"status" : ["active"],
"roles" : ["technical"],
"vcardArray" :
[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "John Doe"],
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2125551213"],
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
["email", {}, "text", "johndoe@example.com"]
]
],
}
]
}
],

View file

@ -14,15 +14,13 @@
"type" : "application/rdap+json"
}
],
"events": [
"remarks": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
],
"vcardArray" :
@ -62,15 +60,13 @@
"type" : "application/rdap+json"
}
],
"events": [
"remarks": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
],
"vcardArray" :

View file

@ -16,371 +16,17 @@
"value": "https://example.com/rdap/domain/cat.example"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "expiration",
"eventDate": "2110-10-08T00:44:59.000Z"
},
{
"eventAction": "last changed",
"eventDate": "2009-05-29T20:13:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"nameservers": [
{
"status": [
"active"
],
"handle": "8-ROID",
"links": [
{
"href": "https://example.com/rdap/nameserver/ns1.cat.lol",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/nameserver/ns1.cat.lol"
}
],
"ldhName": "ns1.cat.lol",
"ipAddresses": {
"v4": [
"1.2.3.4"
]
},
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1999-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "nameserver"
},
{
"status": [
"active"
],
"handle": "1F-ROID",
"links": [
{
"href": "https://example.com/rdap/nameserver/ns2.external.tld",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/nameserver/ns2.external.tld"
}
],
"ldhName": "ns2.external.tld",
"ipAddresses": {
"v6": [
"bad:f00d:cafe::15:beef"
]
},
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1998-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "nameserver"
}
],
"ldhName": "cat.example",
"entities": [
"objectClassName": "domain",
"remarks": [
{
"status": [
"active"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"handle": "1B-ROID",
"roles": [
"administrative"
],
"links": [
{
"href": "https://example.com/rdap/entity/1B-ROID",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/entity/1B-ROID"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1998-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "entity",
"vcardArray": [
"vcard",
[
[
"version",
{},
"text",
"4.0"
],
[
"fn",
{},
"text",
"Mark"
],
[
"org",
{},
"text",
"GOOGLE INCORPORATED <script>"
],
[
"adr",
{},
"text",
[
"",
"",
"123 Example Boulevard <script>",
"KOKOMO",
"BM",
"31337",
"United States"
]
],
[
"tel",
{
"type": [
"voice"
]
},
"uri",
"tel:+1.2126660420"
],
[
"tel",
{
"type": [
"fax"
]
},
"uri",
"tel:+1.2126660420"
],
[
"email",
{},
"text",
"BOFH@cat.lol"
]
]
]
},
{
"status": [
"active"
],
"handle": "1D-ROID",
"roles": [
"technical"
],
"links": [
{
"href": "https://example.com/rdap/entity/1D-ROID",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/entity/1D-ROID"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1997-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "entity",
"vcardArray": [
"vcard",
[
[
"version",
{},
"text",
"4.0"
],
[
"fn",
{},
"text",
"Luke"
],
[
"org",
{},
"text",
"GOOGLE INCORPORATED <script>"
],
[
"adr",
{},
"text",
[
"",
"",
"123 Example Boulevard <script>",
"KOKOMO",
"BM",
"31337",
"United States"
]
],
[
"tel",
{
"type": [
"voice"
]
},
"uri",
"tel:+1.2126660420"
],
[
"tel",
{
"type": [
"fax"
]
},
"uri",
"tel:+1.2126660420"
],
[
"email",
{},
"text",
"bog@cat.lol"
]
]
]
},
{
"status": [
"active"
],
"handle": "19-ROID",
"roles": [
"registrant"
],
"links": [
{
"href": "https://example.com/rdap/entity/19-ROID",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/entity/19-ROID"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1999-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "entity",
"vcardArray": [
"vcard",
[
[
"version",
{},
"text",
"4.0"
],
[
"fn",
{},
"text",
"Matthew"
],
[
"org",
{},
"text",
"GOOGLE INCORPORATED <script>"
],
[
"adr",
{},
"text",
[
"",
"",
"123 Example Boulevard <script>",
"KOKOMO",
"BM",
"31337",
"United States"
]
],
[
"tel",
{
"type": [
"voice"
]
},
"uri",
"tel:+1.2126660420"
],
[
"tel",
{
"type": [
"fax"
]
},
"uri",
"tel:+1.2126660420"
],
[
"email",
{},
"text",
"lol@cat.lol"
]
]
]
"type": "object truncated due to unexplainable reasons"
}
],
"objectClassName": "domain"
]
},
{
"status": [
@ -398,371 +44,17 @@
"value": "https://example.com/rdap/domain/cat.lol"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "expiration",
"eventDate": "2110-10-08T00:44:59.000Z"
},
{
"eventAction": "last changed",
"eventDate": "2009-05-29T20:13:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"nameservers": [
{
"status": [
"active"
],
"handle": "8-ROID",
"links": [
{
"href": "https://example.com/rdap/nameserver/ns1.cat.lol",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/nameserver/ns1.cat.lol"
}
],
"ldhName": "ns1.cat.lol",
"ipAddresses": {
"v4": [
"1.2.3.4"
]
},
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1999-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "nameserver"
},
{
"status": [
"active"
],
"handle": "A-ROID",
"links": [
{
"href": "https://example.com/rdap/nameserver/ns2.cat.lol",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/nameserver/ns2.cat.lol"
}
],
"ldhName": "ns2.cat.lol",
"ipAddresses": {
"v6": [
"bad:f00d:cafe::15:beef"
]
},
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1998-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "nameserver"
}
],
"ldhName": "cat.lol",
"entities": [
"objectClassName": "domain",
"remarks": [
{
"status": [
"active"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"handle": "4-ROID",
"roles": [
"administrative"
],
"links": [
{
"href": "https://example.com/rdap/entity/4-ROID",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/entity/4-ROID"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1998-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "entity",
"vcardArray": [
"vcard",
[
[
"version",
{},
"text",
"4.0"
],
[
"fn",
{},
"text",
"Santa Claus"
],
[
"org",
{},
"text",
"GOOGLE INCORPORATED <script>"
],
[
"adr",
{},
"text",
[
"",
"",
"123 Example Boulevard <script>",
"KOKOMO",
"BM",
"31337",
"United States"
]
],
[
"tel",
{
"type": [
"voice"
]
},
"uri",
"tel:+1.2126660420"
],
[
"tel",
{
"type": [
"fax"
]
},
"uri",
"tel:+1.2126660420"
],
[
"email",
{},
"text",
"BOFH@cat.lol"
]
]
]
},
{
"status": [
"active"
],
"handle": "6-ROID",
"roles": [
"technical"
],
"links": [
{
"href": "https://example.com/rdap/entity/6-ROID",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/entity/6-ROID"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1997-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "entity",
"vcardArray": [
"vcard",
[
[
"version",
{},
"text",
"4.0"
],
[
"fn",
{},
"text",
"The Raven"
],
[
"org",
{},
"text",
"GOOGLE INCORPORATED <script>"
],
[
"adr",
{},
"text",
[
"",
"",
"123 Example Boulevard <script>",
"KOKOMO",
"BM",
"31337",
"United States"
]
],
[
"tel",
{
"type": [
"voice"
]
},
"uri",
"tel:+1.2126660420"
],
[
"tel",
{
"type": [
"fax"
]
},
"uri",
"tel:+1.2126660420"
],
[
"email",
{},
"text",
"bog@cat.lol"
]
]
]
},
{
"status": [
"active"
],
"handle": "2-ROID",
"roles": [
"registrant"
],
"links": [
{
"href": "https://example.com/rdap/entity/2-ROID",
"type": "application/rdap+json",
"rel": "self",
"value": "https://example.com/rdap/entity/2-ROID"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1999-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
}
],
"objectClassName": "entity",
"vcardArray": [
"vcard",
[
[
"version",
{},
"text",
"4.0"
],
[
"fn",
{},
"text",
"Goblin Market"
],
[
"org",
{},
"text",
"GOOGLE INCORPORATED <script>"
],
[
"adr",
{},
"text",
[
"",
"",
"123 Example Boulevard <script>",
"KOKOMO",
"BM",
"31337",
"United States"
]
],
[
"tel",
{
"type": [
"voice"
]
},
"uri",
"tel:+1.2126660420"
],
[
"tel",
{
"type": [
"fax"
]
},
"uri",
"tel:+1.2126660420"
],
[
"email",
{},
"text",
"lol@cat.lol"
]
]
]
"type": "object truncated due to unexplainable reasons"
}
],
"objectClassName": "domain"
]
}
],
"rdapConformance": [

View file

@ -19,15 +19,13 @@
{
"v6" : ["bad:f00d:cafe::15:beef"]
},
"events": [
"remarks": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1999-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
},
@ -50,15 +48,13 @@
"v4" : ["1.2.3.3"]
"v6" : ["bad:f00d:cafe::15:beef"]
},
"events": [
"remarks": [
{
"eventAction": "registration",
"eventActor": "foo",
"eventDate": "1999-01-01T00:00:00.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
}

View file

@ -0,0 +1,31 @@
{
"objectClassName" : "domain",
"handle" : "10-Q9JYB4C",
"ldhName" : "cat.xn--q9jyb4c",
"unicodeName" : "cat.みんな",
"status" :
[
"client delete prohibited",
"client renew prohibited",
"client transfer prohibited",
"server update prohibited"
],
"links" :
[
{
"value" : "http://myserver.google.com/domain/cat.xn--q9jyb4c",
"rel" : "self",
"href" : "http://myserver.google.com/domain/cat.xn--q9jyb4c",
"type" : "application/rdap+json"
}
],
"remarks": [
{
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
}

View file

@ -0,0 +1,30 @@
{
"objectClassName" : "nameserver",
"handle" : "C-ROID",
"ldhName" : "ns3.cat.xn--q9jyb4c",
"unicodeName" : "ns3.cat.みんな",
"status" : ["active"],
"links" :
[
{
"value" : "http://myserver.google.com/nameserver/ns3.cat.xn--q9jyb4c",
"rel" : "self",
"href" : "http://myserver.google.com/nameserver/ns3.cat.xn--q9jyb4c",
"type" : "application/rdap+json"
}
],
"ipAddresses" :
{
"v4" : ["1.2.3.4"],
"v6" : ["bad:f00d:cafe::15:beef"]
},
"remarks": [
{
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
}

View file

@ -0,0 +1,36 @@
{
"objectClassName" : "entity",
"handle" : "2-ROID",
"status" : ["active"],
"roles" : ["registrant"],
"links" :
[
{
"value" : "http://myserver.google.com/entity/2-ROID",
"rel" : "self",
"href" : "http://myserver.google.com/entity/2-ROID",
"type" : "application/rdap+json"
}
],
"vcardArray" :
[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "(◕‿◕)"],
["org", {}, "text", "GOOGLE INCORPORATED <script>"],
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2126660420"],
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2126660420"],
["email", {}, "text", "lol@cat.みんな"]
]
],
"remarks": [
{
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
}

View file

@ -0,0 +1,50 @@
{
"objectClassName" : "entity",
"handle" : "1",
"status" : ["active"],
"roles" : ["registrar"],
"links" :
[
{
"value" : "http://myserver.google.com/entity/1",
"rel" : "self",
"href" : "http://myserver.google.com/entity/1",
"type" : "application/rdap+json"
}
],
"publicIds" :
[
{
"type" : "IANA Registrar ID",
"identifier" : "1"
}
],
"vcardArray" :
[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "みんな"],
["adr", {}, "text", [
"",
"",
"123 Example Boulevard <script>",
"Williamsburg <script>",
"NY",
"11211",
"United States"]],
["tel", {"type" : ["voice"]}, "uri", "tel:+1.2125551212"],
["tel", {"type" : ["fax"]}, "uri", "tel:+1.2125551213"],
["email", {}, "text", "contact-us@example.com"]
]
],
"remarks": [
{
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
}

View file

@ -732,6 +732,25 @@ public class DatastoreHelper {
return persistResource(resource, true);
}
private static <R> void saveResource(final R resource, final boolean wantBackup) {
Saver saver = wantBackup ? ofy().save() : ofy().saveWithoutBackup();
saver.entity(resource);
if (resource instanceof EppResource) {
EppResource eppResource = (EppResource) resource;
assertWithMessage("Cannot persist an EppResource with a missing repoId in tests")
.that(eppResource.getRepoId()).isNotEmpty();
Key<EppResource> eppResourceKey = Key.create(eppResource);
saver.entity(EppResourceIndex.create(eppResourceKey));
if (resource instanceof ForeignKeyedEppResource) {
saver.entity(ForeignKeyIndex.create(eppResource, eppResource.getDeletionTime()));
}
if (resource instanceof DomainApplication) {
saver.entity(
DomainApplicationIndex.createUpdatedInstance((DomainApplication) resource));
}
}
}
private static <R> R persistResource(final R resource, final boolean wantBackup) {
assertWithMessage("Attempting to persist a Builder is almost certainly an error in test code")
.that(resource)
@ -739,22 +758,7 @@ public class DatastoreHelper {
ofy().transact(new VoidWork() {
@Override
public void vrun() {
Saver saver = wantBackup ? ofy().save() : ofy().saveWithoutBackup();
saver.entity(resource);
if (resource instanceof EppResource) {
EppResource eppResource = (EppResource) resource;
assertWithMessage("Cannot persist an EppResource with a missing repoId in tests")
.that(eppResource.getRepoId()).isNotEmpty();
Key<EppResource> eppResourceKey = Key.create(eppResource);
saver.entity(EppResourceIndex.create(eppResourceKey));
if (resource instanceof ForeignKeyedEppResource) {
saver.entity(ForeignKeyIndex.create(eppResource, eppResource.getDeletionTime()));
}
if (resource instanceof DomainApplication) {
saver.entity(
DomainApplicationIndex.createUpdatedInstance((DomainApplication) resource));
}
}
saveResource(resource, wantBackup);
}});
// Force the session to be cleared so that when we read it back, we read from the datastore
// and not from the transaction cache or memcache.
@ -762,6 +766,34 @@ public class DatastoreHelper {
return ofy().load().entity(resource).now();
}
public static <R> void persistResources(final Iterable<R> resources) {
persistResources(resources, false);
}
private static <R> void persistResources(final Iterable<R> resources, final boolean wantBackup) {
for (R resource : resources) {
assertWithMessage("Attempting to persist a Builder is almost certainly an error in test code")
.that(resource)
.isNotInstanceOf(Buildable.Builder.class);
}
// Persist domains ten at a time, to avoid exceeding the entity group limit.
for (final List<R> chunk : Iterables.partition(resources, 10)) {
ofy().transact(new VoidWork() {
@Override
public void vrun() {
for (R resource : chunk) {
saveResource(resource, wantBackup);
}
}});
}
// Force the session to be cleared so that when we read it back, we read from the datastore
// and not from the transaction cache or memcache.
ofy().clearSessionCache();
for (R resource : resources) {
ofy().load().entity(resource).now();
}
}
/**
* Saves an {@link EppResource} with partial history and commit log entries.
*