Fix handling of DAPR_API_TOKEN

Fixes: #655

This fixes a functional bug in how we initialize the default settings of
based on the `DAPI_API_TOKEN` environment variable.

Additional, the `CreateInvokeMethodRequest` family of methods were
missing API token support. This has been added.
This commit is contained in:
Ryan Nowak 2021-04-16 15:01:27 -07:00
parent 5e5a42c96e
commit 9104c6624c
7 changed files with 103 additions and 21 deletions

View File

@ -34,7 +34,7 @@ namespace Dapr.Client
/// Gets the <see cref="JsonSerializerOptions" /> used for JSON serialization operations.
/// </summary>
public abstract JsonSerializerOptions JsonSerializerOptions { get; }
/// <summary>
/// <para>
/// Creates an <see cref="HttpClient" /> that can be used to perform Dapr service
@ -76,7 +76,7 @@ namespace Dapr.Client
}
var httpClient = new HttpClient(handler);
if (appId is string)
{
try
@ -92,14 +92,14 @@ namespace Dapr.Client
return httpClient;
}
internal static KeyValuePair<string, string> GetDaprApiTokenHeader(string apiToken)
internal static KeyValuePair<string, string>? GetDaprApiTokenHeader(string apiToken)
{
KeyValuePair<string, string> apiTokenHeader = default;
if(!string.IsNullOrWhiteSpace(apiToken))
if (string.IsNullOrWhiteSpace(apiToken))
{
apiTokenHeader = new KeyValuePair<string, string>("dapr-api-token", apiToken);
return null;
}
return apiTokenHeader;
return new KeyValuePair<string, string>("dapr-api-token", apiToken);
}
/// <summary>

View File

@ -34,7 +34,7 @@ namespace Dapr.Client
private readonly GrpcChannel channel;
private readonly Autogenerated.Dapr.DaprClient client;
private readonly KeyValuePair<string, string> apiTokenHeader;
private readonly KeyValuePair<string, string>? apiTokenHeader;
// property exposed for testing purposes
internal Autogenerated.Dapr.DaprClient Client => client;
@ -47,7 +47,7 @@ namespace Dapr.Client
HttpClient httpClient,
Uri httpEndpoint,
JsonSerializerOptions jsonSerializerOptions,
KeyValuePair<string, string> apiTokenHeader)
KeyValuePair<string, string>? apiTokenHeader)
{
this.channel = channel;
this.client = inner;
@ -263,6 +263,11 @@ namespace Dapr.Client
}
};
if (this.apiTokenHeader is not null)
{
request.Headers.TryAddWithoutValidation(this.apiTokenHeader.Value.Key, this.apiTokenHeader.Value.Value);
}
return request;
}
@ -1031,11 +1036,11 @@ namespace Dapr.Client
{
var options = new CallOptions(headers: headers ?? new Metadata(), cancellationToken: cancellationToken);
// add token for dapr api token based authentication
if ((this.apiTokenHeader.Key, this.apiTokenHeader.Value) != default)
{
options.Headers.Add(this.apiTokenHeader.Key, this.apiTokenHeader.Value);
}
// add token for dapr api token based authentication
if (this.apiTokenHeader is not null)
{
options.Headers.Add(this.apiTokenHeader.Value.Key, this.apiTokenHeader.Value.Value);
}
return options;
}

View File

@ -93,9 +93,9 @@ namespace Dapr.Client
try
{
var apiTokenHeader = DaprClient.GetDaprApiTokenHeader(this.apiToken);
if ((apiTokenHeader.Key, apiTokenHeader.Value) != default)
if (apiTokenHeader is not null)
{
request.Headers.Add(apiTokenHeader.Key, apiTokenHeader.Value);
request.Headers.Add(apiTokenHeader.Value.Key, apiTokenHeader.Value.Value);
}
request.RequestUri = rewritten;

View File

@ -20,10 +20,9 @@ namespace Dapr
// for a running process.
if (apiToken == null)
{
var value = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
// Treat empty the same as null since it's an environment variable
apiToken = value == string.Empty ? null : apiToken;
var value = Environment.GetEnvironmentVariable("DAPR_API_TOKEN");
apiToken = (value == string.Empty) ? null : value;
}
return apiToken;

View File

@ -86,7 +86,8 @@ namespace Dapr.AspNetCore.Test
var builder = new DaprClientBuilder();
builder.UseDaprApiToken("test_token");
var entry = DaprClient.GetDaprApiTokenHeader(builder.DaprApiToken);
Assert.Equal("test_token", entry.Value);
Assert.NotNull(entry);
Assert.Equal("test_token", entry.Value.Value);
}
[Fact]

View File

@ -378,6 +378,82 @@ namespace Dapr.Client.Test
Assert.Equal(new Uri(expected).AbsoluteUri, request.RequestUri.AbsoluteUri);
}
[Fact]
public async Task CreateInvokeMethodRequest_WithoutApiToken_CreatesHttpRequestWithoutApiTokenHeader()
{
await using var client = TestClient.CreateForDaprClient(c =>
{
c
.UseGrpcEndpoint("http://localhost")
.UseHttpEndpoint("https://test-endpoint:3501")
.UseJsonSerializationOptions(this.jsonSerializerOptions)
.UseDaprApiToken(null);
});
var request = client.InnerClient.CreateInvokeMethodRequest("test-app", "test");
Assert.False(request.Headers.TryGetValues("dapr-api-token", out _));
}
[Fact]
public async Task CreateInvokeMethodRequest_WithApiToken_CreatesHttpRequestWithApiTokenHeader()
{
await using var client = TestClient.CreateForDaprClient(c =>
{
c
.UseGrpcEndpoint("http://localhost")
.UseHttpEndpoint("https://test-endpoint:3501")
.UseJsonSerializationOptions(this.jsonSerializerOptions)
.UseDaprApiToken("test-token");
});
var request = client.InnerClient.CreateInvokeMethodRequest("test-app", "test");
Assert.True(request.Headers.TryGetValues("dapr-api-token", out var values));
Assert.Equal("test-token", Assert.Single(values));
}
[Fact]
public async Task CreateInvokeMethodRequest_WithoutApiTokenAndWithData_CreatesHttpRequestWithoutApiTokenHeader()
{
await using var client = TestClient.CreateForDaprClient(c =>
{
c
.UseGrpcEndpoint("http://localhost")
.UseHttpEndpoint("https://test-endpoint:3501")
.UseJsonSerializationOptions(this.jsonSerializerOptions)
.UseDaprApiToken(null);
});
var data = new Widget
{
Color = "red",
};
var request = client.InnerClient.CreateInvokeMethodRequest("test-app", "test", data);
Assert.False(request.Headers.TryGetValues("dapr-api-token", out _));
}
[Fact]
public async Task CreateInvokeMethodRequest_WithApiTokenAndData_CreatesHttpRequestWithApiTokenHeader()
{
await using var client = TestClient.CreateForDaprClient(c =>
{
c
.UseGrpcEndpoint("http://localhost")
.UseHttpEndpoint("https://test-endpoint:3501")
.UseJsonSerializationOptions(this.jsonSerializerOptions)
.UseDaprApiToken("test-token");
});
var data = new Widget
{
Color = "red",
};
var request = client.InnerClient.CreateInvokeMethodRequest("test-app", "test", data);
Assert.True(request.Headers.TryGetValues("dapr-api-token", out var values));
Assert.Equal("test-token", Assert.Single(values));
}
[Fact]
public async Task CreateInvokeMethodRequest_WithData_CreatesJsonContent()
{

View File

@ -64,7 +64,8 @@ namespace Dapr.Client
{
var token = "test_token";
var entry = DaprClient.GetDaprApiTokenHeader(token);
Assert.Equal("test_token", entry.Value);
Assert.NotNull(entry);
Assert.Equal("test_token", entry.Value.Value);
}
[Fact]