Skip to content
Merged
17 changes: 17 additions & 0 deletions sdk/appconfiguration/azure-data-appconfiguration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,22 @@ ConfigurationSetting setting = client.setReadOnly("some_key", "some_label", fals

When you interact with App Configuration using this Java client library, errors returned by the service correspond to the same HTTP status codes returned for [REST API][rest_api] requests. For example, if you try to retrieve a configuration setting that doesn't exist in your configuration store, a `404` error is returned, indicating `Not Found`.

App Configuration provides a way to define customized headers through `Context` object in the public API.

```java
// Add your headers
HttpHeaders headers = new HttpHeaders();
headers.put("my-header1", "my-header1-value");
headers.put("my-header2", "my-header2-value");
headers.put("my-header3", "my-header3-value");
// Call API by passing headers in Context.
configurationClient.addConfigurationSettingWithResponse(
new ConfigurationSetting().setKey("key").setValue("value"),
new Context(AddHeadersFromContextPolicy.AZURE_REQUEST_HTTP_HEADERS_KEY, headers));
// Above three HttpHeader will be added in outgoing HttpRequest.
```
For more detail information, check out the [AddHeadersFromContextPolicy][add_headers_from_context_policy]

## Next steps

- Samples are explained in detail [here][samples_readme].
Expand Down Expand Up @@ -338,5 +354,6 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m
[source_code]: src
[spring_quickstart]: https://docs.microsoft.com/azure/azure-app-configuration/quickstart-java-spring-app
[performance_tuning]: https://github.com/Azure/azure-sdk-for-java/wiki/Performance-Tuning
[add_headers_from_context_policy]: https://github.com/Azure/azure-sdk-for-java/blob/master/sdk/core/azure-core/src/main/java/com/azure/core/http/policy/AddHeadersFromContextPolicy.java

![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-java%2Fsdk%2Fappconfiguration%2Fazure-data-appconfiguration%2FREADME.png)
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpPipelineBuilder;
import com.azure.core.http.policy.AddDatePolicy;
import com.azure.core.http.policy.AddHeadersFromContextPolicy;
import com.azure.core.http.policy.AddHeadersPolicy;
import com.azure.core.http.policy.BearerTokenAuthenticationPolicy;
import com.azure.core.http.policy.HttpLogDetailLevel;
Expand Down Expand Up @@ -179,6 +180,7 @@ public ConfigurationAsyncClient buildAsyncClient() {
policies.add(new UserAgentPolicy(httpLogOptions.getApplicationId(), clientName, clientVersion,
buildConfiguration));
policies.add(new RequestIdPolicy());
policies.add(new AddHeadersFromContextPolicy());
policies.add(new AddHeadersPolicy(headers));
policies.add(new AddDatePolicy());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// Licensed under the MIT License.
package com.azure.data.appconfiguration;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import com.azure.core.exception.HttpResponseException;
import com.azure.core.exception.ResourceExistsException;
import com.azure.core.exception.ResourceNotFoundException;
import com.azure.core.http.HttpHeaders;
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
import com.azure.core.http.policy.AddHeadersFromContextPolicy;
import com.azure.core.http.policy.HttpLogDetailLevel;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.core.http.policy.RetryPolicy;
Expand All @@ -23,12 +22,16 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import reactor.util.context.Context;

import java.net.HttpURLConnection;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class ConfigurationAsyncClientTest extends ConfigurationClientTestBase {
private final ClientLogger logger = new ClientLogger(ConfigurationAsyncClientTest.class);
private static final String NO_LABEL = null;
Expand Down Expand Up @@ -869,5 +872,18 @@ public void deleteAllSettings() {
return client.deleteConfigurationSettingWithResponse(configurationSetting, false);
}).blockLast();
}

@Test
public void addHeadersFromContextPolicyTest() {
final HttpHeaders headers = getCustomizedHeaders();
addHeadersFromContextPolicyRunner(expected ->
StepVerifier.create(client.addConfigurationSettingWithResponse(expected)
.subscriberContext(Context.of(AddHeadersFromContextPolicy.AZURE_REQUEST_HTTP_HEADERS_KEY, headers)))
.assertNext(response -> {
final HttpHeaders requestHeaders = response.getRequest().getHeaders();
assertContainsHeaders(headers, requestHeaders);
})
.verifyComplete());
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,32 @@
// Licensed under the MIT License.
package com.azure.data.appconfiguration;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import com.azure.core.exception.HttpResponseException;
import com.azure.core.exception.ResourceExistsException;
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.data.appconfiguration.models.ConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingFields;
import com.azure.data.appconfiguration.models.SettingSelector;
import com.azure.core.exception.ResourceNotFoundException;
import com.azure.core.http.HttpHeaders;
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
import com.azure.core.http.policy.AddHeadersFromContextPolicy;
import com.azure.core.http.policy.HttpLogDetailLevel;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.core.http.policy.RetryPolicy;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.http.rest.Response;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import com.azure.data.appconfiguration.models.ConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingFields;
import com.azure.data.appconfiguration.models.SettingSelector;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.net.HttpURLConnection;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class ConfigurationClientTest extends ConfigurationClientTestBase {
private final ClientLogger logger = new ClientLogger(ConfigurationClientTest.class);
Expand Down Expand Up @@ -644,4 +646,16 @@ public void deleteAllSettings() {
client.deleteConfigurationSettingWithResponse(configurationSetting, false, Context.NONE).getValue();
});
}

@Test
public void addHeadersFromContextPolicyTest() {
final HttpHeaders headers = getCustomizedHeaders();
addHeadersFromContextPolicyRunner(expected -> {
final Response<ConfigurationSetting> response =
client.addConfigurationSettingWithResponse(expected,
new Context(AddHeadersFromContextPolicy.AZURE_REQUEST_HTTP_HEADERS_KEY, headers));
assertContainsHeaders(headers, response.getRequest().getHeaders());
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@
// Licensed under the MIT License.
package com.azure.data.appconfiguration;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.HttpHeaders;
import com.azure.core.http.rest.Response;
import com.azure.core.test.TestBase;
import com.azure.core.util.Configuration;
Expand All @@ -19,6 +13,9 @@
import com.azure.data.appconfiguration.models.ConfigurationSetting;
import com.azure.data.appconfiguration.models.SettingFields;
import com.azure.data.appconfiguration.models.SettingSelector;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
Expand All @@ -34,8 +31,13 @@
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

public abstract class ConfigurationClientTestBase extends TestBase {
private static final String AZURE_APPCONFIG_CONNECTION_STRING = "AZURE_APPCONFIG_CONNECTION_STRING";
Expand Down Expand Up @@ -379,6 +381,17 @@ void listRevisionsWithMultipleLabelsRunner(String key, String label, String labe
@Test
public abstract void deleteAllSettings();

@Test
public abstract void addHeadersFromContextPolicyTest();

void addHeadersFromContextPolicyRunner(Consumer<ConfigurationSetting> testRunner) {
final String key = getKey();
final String value = "newValue";

final ConfigurationSetting newConfiguration = new ConfigurationSetting().setKey(key).setValue(value);
testRunner.accept(newConfiguration);
}

/**
* Helper method to verify that the RestResponse matches what was expected. This method assumes a response status of 200.
*
Expand Down Expand Up @@ -552,4 +565,37 @@ static boolean equalsArray(List<ConfigurationSetting> settings1, List<Configurat
}
return true;
}

/**
* Helper method that sets up HttpHeaders
*
* @return the http headers
*/
static HttpHeaders getCustomizedHeaders() {
final String headerOne = "my-header1";
final String headerTwo = "my-header2";
final String headerThree = "my-header3";

final String headerOneValue = "my-header1-value";
final String headerTwoValue = "my-header2-value";
final String headerThreeValue = "my-header3-value";

final HttpHeaders headers = new HttpHeaders();
headers.put(headerOne, headerOneValue);
headers.put(headerTwo, headerTwoValue);
headers.put(headerThree, headerThreeValue);

return headers;
}

/**
* Helper method that check if the {@code headerContainer} contains {@code headers}.
*
* @param headers the headers that been checked
* @param headerContainer The headers container that check if the {@code headers} exist in it.
*/
static void assertContainsHeaders(HttpHeaders headers, HttpHeaders headerContainer) {
headers.stream().forEach(httpHeader ->
assertEquals(headerContainer.getValue(httpHeader.getName()), httpHeader.getValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"networkCallRecords" : [ {
"Method" : "PUT",
"Uri" : "https://appconfigtestshawnfang.azconfig.io/kv/key50977280758?api-version=1.0",
"Headers" : {
"User-Agent" : "azsdk-java-UnknownName/UnknownVersion (11.0.4; Windows 10 10.0)",
"x-ms-client-request-id" : "e9b22ff5-88bb-43dc-9fea-326b62ddcd14",
"Content-Type" : "application/json"
},
"Response" : {
"Transfer-Encoding" : "chunked",
"Server" : "openresty/1.15.8.1",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Methods" : "GET, PUT, POST, DELETE, PATCH, OPTIONS",
"Connection" : "keep-alive",
"Last-Modified" : "Thu, 12 Dec 2019 01:34:03 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Date" : "Thu, 12 Dec 2019 01:34:02 GMT",
"Access-Control-Allow-Headers" : "DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization, x-ms-client-request-id, x-ms-command-name, x-ms-content-sha256, x-ms-date, host, Accept, Accept-Datetime, Date, If-Match, If-None-Match, Sync-Token, x-ms-return-client-request-id, ETag, Last-Modified, Link, Memento-Datetime, x-ms-retry-after, x-ms-request-id, WWW-Authenticate",
"x-ms-correlation-request-id" : "d17cf096-d4b2-4e9b-8989-b995883f9220",
"Strict-Transport-Security" : "max-age=15724800; includeSubDomains",
"Access-Control-Expose-Headers" : "DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization, x-ms-client-request-id, x-ms-command-name, x-ms-content-sha256, x-ms-date, host, Accept, Accept-Datetime, Date, If-Match, If-None-Match, Sync-Token, x-ms-return-client-request-id, ETag, Last-Modified, Link, Memento-Datetime, x-ms-retry-after, x-ms-request-id, WWW-Authenticate",
"ETag" : "\"C9lwXgKsyniqCMiZQEMXehlxbJc\"",
"Access-Control-Allow-Credentials" : "true",
"Sync-Token" : "zAJw6V16=MDotMSM2NDQ5OTU=;sn=644995",
"x-ms-request-id" : "d17cf096-d4b2-4e9b-8989-b995883f9220",
"Body" : "{\"etag\":\"C9lwXgKsyniqCMiZQEMXehlxbJc\",\"key\":\"key50977280758\",\"label\":null,\"content_type\":null,\"value\":\"newValue\",\"tags\":{},\"locked\":false,\"last_modified\":\"2019-12-12T01:34:03+00:00\"}",
"x-ms-client-request-id" : "e9b22ff5-88bb-43dc-9fea-326b62ddcd14",
"Content-Type" : "application/vnd.microsoft.appconfig.kv+json; charset=utf-8"
},
"Exception" : null
}, {
"Method" : "GET",
"Uri" : "https://appconfigtestshawnfang.azconfig.io/kv?key=key50977%2a&api-version=1.0",
"Headers" : {
"User-Agent" : "azsdk-java-UnknownName/UnknownVersion (11.0.4; Windows 10 10.0)",
"x-ms-client-request-id" : "d8137165-1841-4190-a0a4-8dce7975d4c5",
"Content-Type" : "application/json"
},
"Response" : {
"Transfer-Encoding" : "chunked",
"Server" : "openresty/1.15.8.1",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Methods" : "GET, PUT, POST, DELETE, PATCH, OPTIONS",
"Connection" : "keep-alive",
"retry-after" : "0",
"StatusCode" : "200",
"Date" : "Thu, 12 Dec 2019 01:34:02 GMT",
"Access-Control-Allow-Headers" : "DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization, x-ms-client-request-id, x-ms-command-name, x-ms-content-sha256, x-ms-date, host, Accept, Accept-Datetime, Date, If-Match, If-None-Match, Sync-Token, x-ms-return-client-request-id, ETag, Last-Modified, Link, Memento-Datetime, x-ms-retry-after, x-ms-request-id, WWW-Authenticate",
"x-ms-correlation-request-id" : "54f432e3-19dc-4740-88ea-4eb9568692da",
"Strict-Transport-Security" : "max-age=15724800; includeSubDomains",
"Access-Control-Expose-Headers" : "DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization, x-ms-client-request-id, x-ms-command-name, x-ms-content-sha256, x-ms-date, host, Accept, Accept-Datetime, Date, If-Match, If-None-Match, Sync-Token, x-ms-return-client-request-id, ETag, Last-Modified, Link, Memento-Datetime, x-ms-retry-after, x-ms-request-id, WWW-Authenticate",
"Access-Control-Allow-Credentials" : "true",
"Sync-Token" : "zAJw6V16=MDotMSM2NDQ5OTU=;sn=644995",
"x-ms-request-id" : "54f432e3-19dc-4740-88ea-4eb9568692da",
"Body" : "{\"items\":[{\"etag\":\"C9lwXgKsyniqCMiZQEMXehlxbJc\",\"key\":\"key50977280758\",\"label\":null,\"content_type\":null,\"value\":\"newValue\",\"tags\":{},\"locked\":false,\"last_modified\":\"2019-12-12T01:34:03+00:00\"}]}",
"x-ms-client-request-id" : "d8137165-1841-4190-a0a4-8dce7975d4c5",
"Content-Type" : "application/vnd.microsoft.appconfig.kvset+json; charset=utf-8"
},
"Exception" : null
}, {
"Method" : "DELETE",
"Uri" : "https://appconfigtestshawnfang.azconfig.io/kv/key50977280758?api-version=1.0",
"Headers" : {
"User-Agent" : "azsdk-java-UnknownName/UnknownVersion (11.0.4; Windows 10 10.0)",
"x-ms-client-request-id" : "6583721c-3230-4d6c-85b7-24fc3dd6d419",
"Content-Type" : "application/json"
},
"Response" : {
"Transfer-Encoding" : "chunked",
"Server" : "openresty/1.15.8.1",
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Methods" : "GET, PUT, POST, DELETE, PATCH, OPTIONS",
"Connection" : "keep-alive",
"Last-Modified" : "Thu, 12 Dec 2019 01:34:03 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Date" : "Thu, 12 Dec 2019 01:34:02 GMT",
"Access-Control-Allow-Headers" : "DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization, x-ms-client-request-id, x-ms-command-name, x-ms-content-sha256, x-ms-date, host, Accept, Accept-Datetime, Date, If-Match, If-None-Match, Sync-Token, x-ms-return-client-request-id, ETag, Last-Modified, Link, Memento-Datetime, x-ms-retry-after, x-ms-request-id, WWW-Authenticate",
"x-ms-correlation-request-id" : "bd84e592-47bb-42f3-b0dc-2f58afba337e",
"Strict-Transport-Security" : "max-age=15724800; includeSubDomains",
"Access-Control-Expose-Headers" : "DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization, x-ms-client-request-id, x-ms-command-name, x-ms-content-sha256, x-ms-date, host, Accept, Accept-Datetime, Date, If-Match, If-None-Match, Sync-Token, x-ms-return-client-request-id, ETag, Last-Modified, Link, Memento-Datetime, x-ms-retry-after, x-ms-request-id, WWW-Authenticate",
"ETag" : "\"C9lwXgKsyniqCMiZQEMXehlxbJc\"",
"Access-Control-Allow-Credentials" : "true",
"Sync-Token" : "zAJw6V16=MDotMSM2NDQ5OTY=;sn=644996",
"x-ms-request-id" : "bd84e592-47bb-42f3-b0dc-2f58afba337e",
"Body" : "{\"etag\":\"C9lwXgKsyniqCMiZQEMXehlxbJc\",\"key\":\"key50977280758\",\"label\":null,\"content_type\":null,\"value\":\"newValue\",\"tags\":{},\"locked\":false,\"last_modified\":\"2019-12-12T01:34:03+00:00\"}",
"x-ms-client-request-id" : "6583721c-3230-4d6c-85b7-24fc3dd6d419",
"Content-Type" : "application/vnd.microsoft.appconfig.kv+json; charset=utf-8"
},
"Exception" : null
} ],
"variables" : [ "key50977", "b9ec5bff", "key50977280758" ]
}