Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
Expand Down Expand Up @@ -298,15 +299,10 @@ private HttpResponse<byte[]> fetchWithRetries() throws IOException, InterruptedE

private HttpRequest buildRequest() {
final HttpRequest.Builder request =
HttpRequest.newBuilder(this.endpoint)
HttpRequest.newBuilder(endpointForCapabilities(this.endpoint, EvaluatorCapabilities.supported()))
.timeout(this.requestTimeout)
.header("Accept-Encoding", "gzip");
Headers.addMetadata(request);
if (EvaluatorCapabilities.supported()
.contains(EvaluatorCapabilities.DEPENDENT_FLAG_VARIANT_KEY_V1)) {
request.header(
"X-DD-FEATURE-FLAGS-CAPABILITIES", EvaluatorCapabilities.DEPENDENT_FLAG_VARIANT_KEY_V1);
}
if (this.apiKey != null) {
request.header("DD-API-KEY", this.apiKey);
}
Expand All @@ -317,6 +313,39 @@ private HttpRequest buildRequest() {
return request.GET().build();
}

static URI endpointForCapabilities(final URI endpoint, final Set<String> capabilities) {
if (!capabilities.contains(EvaluatorCapabilities.DEPENDENT_FLAG_VARIANT_KEY_V1)) {
return endpoint;
}
final String parameter = EvaluatorCapabilities.DEPENDENT_FLAGS_VARIANT_KEY_QUERY_PARAMETER;
final StringBuilder query = new StringBuilder();
if (endpoint.getRawQuery() != null) {
for (final String item : endpoint.getRawQuery().split("&", -1)) {
if (!item.equals(parameter) && !item.startsWith(parameter + "=")) {
if (query.length() > 0) {
query.append('&');
}
query.append(item);
}
}
}
if (query.length() > 0) {
query.append('&');
}
query
.append(parameter)
.append('=')
.append(EvaluatorCapabilities.DEPENDENT_FLAGS_VARIANT_KEY_QUERY_VERSION);

final String endpointText = endpoint.toString();
final int fragmentStart = endpointText.indexOf('#');
final String fragment = fragmentStart < 0 ? "" : endpointText.substring(fragmentStart);
final String withoutFragment = fragmentStart < 0 ? endpointText : endpointText.substring(0, fragmentStart);
final int queryStart = withoutFragment.indexOf('?');
final String path = queryStart < 0 ? withoutFragment : withoutFragment.substring(0, queryStart);
return URI.create(path + "?" + query + fragment);
}

private synchronized void warn(final String message, final Object... arguments) {
final long now = System.nanoTime();
if (this.lastWarningNanos == 0 || now - this.lastWarningNanos >= WARNING_INTERVAL_NANOS) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/** Capabilities supported by both local evaluation and exposure reporting. */
public final class EvaluatorCapabilities {
public static final String DEPENDENT_FLAG_VARIANT_KEY_V1 = "dependent-flag-variant-key-v1";
public static final String DEPENDENT_FLAGS_VARIANT_KEY_QUERY_PARAMETER =
"cap_dependent-flags-variant-key";
public static final String DEPENDENT_FLAGS_VARIANT_KEY_QUERY_VERSION = "v1";

private EvaluatorCapabilities() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.net.http.HttpClient;
import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.FutureTask;
Expand Down Expand Up @@ -174,6 +175,28 @@ void sendsApiKeyAndMetadataHeaders() throws Exception {
assertNull(request.header("X-DD-FEATURE-FLAGS-CAPABILITIES"));
}

@Test
void carriesEvaluatorCapabilityAsQueryParameter() {
final URI endpoint = URI.create("https://example.test/ufc?token=preserved");

assertEquals(endpoint, CdnConfigurationSource.endpointForCapabilities(endpoint, Set.of()));
assertEquals(
endpoint,
CdnConfigurationSource.endpointForCapabilities(endpoint, Set.of("unknown-v1")));
assertEquals(
URI.create(
"https://example.test/ufc?token=preserved&cap_dependent-flags-variant-key=v1"),
CdnConfigurationSource.endpointForCapabilities(
endpoint, Set.of("dependent-flag-variant-key-v1")));
assertEquals(
URI.create(
"https://example.test/ufc?token=preserved&cap_dependent-flags-variant-key=v1#section"),
CdnConfigurationSource.endpointForCapabilities(
URI.create(
"https://example.test/ufc?cap_dependent-flags-variant-key=old&token=preserved#section"),
Set.of("dependent-flag-variant-key-v1")));
}

@Test
void appliesJsonApiConfiguration() {
this.server.enqueue(200, CONFIG, "ETag", "\"v1\"");
Expand Down
Loading