diff --git a/src/main/java/codes/thischwa/cf/CfDnsClient.java b/src/main/java/codes/thischwa/cf/CfDnsClient.java index 6244bc2..f71d69d 100644 --- a/src/main/java/codes/thischwa/cf/CfDnsClient.java +++ b/src/main/java/codes/thischwa/cf/CfDnsClient.java @@ -233,20 +233,38 @@ public class CfDnsClient extends CfBasicHttpClient { public List recordGet(ZoneEntity zone, String sld, @Nullable RecordType... types) throws CloudflareApiException { String fqdn = buildFqdn(zone, sld); - String endpoint = buildEndpointWithTypeFilters(zone.getId(), fqdn, types); + String endpoint = buildEndpointWithTypeFilters(CfRequest.RECORD_INFO_NAME.buildPath(zone.getId(), fqdn), types); RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class); checkResponse(resp, false); return resp.getResult(); } - private String buildEndpointWithTypeFilters(String zoneId, String fqdn, @Nullable RecordType... types) { - String baseEndpoint = CfRequest.RECORD_INFO_NAME.buildPath(zoneId, fqdn); + /** + * Retrieves a list of all DNS records for a given zone. + * Optionally filters by one or more DNS record types. + * + * @param zone The zone entity containing information about the domain zone. + * @param types Optional parameter specifying one or more DNS record types to filter the results. + * @return A list of {@code RecordEntity} objects representing the DNS records for the specified zone. + * @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API + */ + public List recordList(ZoneEntity zone, RecordType... types) + throws CloudflareApiException { + String endpoint = buildEndpointWithTypeFilters(CfRequest.RECORD_LIST.buildPath(zone.getId()), types); + RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class); + checkResponse(resp, false); + return resp.getResult(); + } + + private String buildEndpointWithTypeFilters(String baseEndpoint, @Nullable RecordType... types) { if (types == null || types.length == 0) { return baseEndpoint; } StringBuilder endpoint = new StringBuilder(baseEndpoint); + String separator = baseEndpoint.contains("?") ? "&" : "?"; for (RecordType type : types) { - endpoint.append("&type=").append(type); + endpoint.append(separator).append("type=").append(type); + separator = "&"; } return endpoint.toString(); } diff --git a/src/main/java/codes/thischwa/cf/CfRequest.java b/src/main/java/codes/thischwa/cf/CfRequest.java index 63fd18e..dcf0fe0 100644 --- a/src/main/java/codes/thischwa/cf/CfRequest.java +++ b/src/main/java/codes/thischwa/cf/CfRequest.java @@ -20,6 +20,12 @@ public enum CfRequest { */ ZONE_INFO("/zones?name=%s"), + /** + * Represents the API endpoint path for retrieving information about DNS records within a + * specific DNS zone. The endpoint path includes a placeholder for the zone identifier, which + * needs to be provided to construct the complete path. + */ + RECORD_LIST("/zones/%s/dns_records"), /** * Represents the API endpoint path for creating a new DNS record within a specific DNS zone. The * endpoint path includes a placeholder for the zone identifier, which needs to be provided to diff --git a/src/main/java/codes/thischwa/cf/fluent/ZoneOperations.java b/src/main/java/codes/thischwa/cf/fluent/ZoneOperations.java index 23336c1..7eebeed 100644 --- a/src/main/java/codes/thischwa/cf/fluent/ZoneOperations.java +++ b/src/main/java/codes/thischwa/cf/fluent/ZoneOperations.java @@ -28,4 +28,12 @@ public interface ZoneOperations { * @throws CloudflareApiException if the zone cannot be found or accessed */ RecordOperations record(String sld, @Nullable RecordType... types) throws CloudflareApiException; + /** + * Lists all DNS records within the zone, optionally filtered by types. + * + * @param types optional DNS record types to filter by + * @return a list of RecordEntity objects matching the criteria + * @throws CloudflareApiException if an error occurs while retrieving records + */ + java.util.List list(@Nullable RecordType... types) throws CloudflareApiException; } diff --git a/src/main/java/codes/thischwa/cf/fluent/ZoneOperationsImpl.java b/src/main/java/codes/thischwa/cf/fluent/ZoneOperationsImpl.java index 36ae33b..97bdae4 100644 --- a/src/main/java/codes/thischwa/cf/fluent/ZoneOperationsImpl.java +++ b/src/main/java/codes/thischwa/cf/fluent/ZoneOperationsImpl.java @@ -2,8 +2,10 @@ package codes.thischwa.cf.fluent; import codes.thischwa.cf.CfDnsClient; import codes.thischwa.cf.CloudflareApiException; +import codes.thischwa.cf.model.RecordEntity; import codes.thischwa.cf.model.RecordType; import codes.thischwa.cf.model.ZoneEntity; +import java.util.List; import org.jetbrains.annotations.Nullable; /** @@ -34,4 +36,9 @@ public class ZoneOperationsImpl implements ZoneOperations { public RecordOperations record(String sld, @Nullable RecordType... types) throws CloudflareApiException { return new RecordOperationsImpl(client, zone, sld, types); } + + @Override + public List list(@Nullable RecordType... types) throws CloudflareApiException { + return client.recordList(zone, types); + } } diff --git a/src/test/java/codes/thischwa/cf/CfClientTest.java b/src/test/java/codes/thischwa/cf/CfClientTest.java index 19b70dc..2eb5bb4 100644 --- a/src/test/java/codes/thischwa/cf/CfClientTest.java +++ b/src/test/java/codes/thischwa/cf/CfClientTest.java @@ -153,6 +153,23 @@ public class CfClientTest { } } + // test recordList without SLD + List fullList = client.recordList(z); + assertTrue(fullList.size() >= 2); + assertTrue(fullList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId()))); + assertTrue(fullList.stream().anyMatch(re -> re.getId().equals(createdRe2.getId()))); + + // test recordList with types without SLD + List aList = client.recordList(z, RecordType.A); + assertTrue(aList.size() >= 1); + assertTrue(aList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId()))); + assertTrue(aList.stream().noneMatch(re -> re.getId().equals(createdRe2.getId()))); + + // test fluent api list + List fluentList = client.zone(ZONE_STR).list(RecordType.A); + assertTrue(fluentList.size() >= 1); + assertTrue(fluentList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId()))); + // update AAAA record createdRe2.setContent("2a0a:4cc0:c0:2e4::2"); client.recordUpdate(z, createdRe2);