Skip to content

Commit

Permalink
Optimization in order to not add some overhead time for the "normal" …
Browse files Browse the repository at this point in the history
…use case

Signed-off-by: TWEESTY <chausse.nicolas@gmail.com>
  • Loading branch information
TWEESTY committed Feb 9, 2024
1 parent 57f778a commit 07a75f3
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 18 deletions.
4 changes: 3 additions & 1 deletion src/Dapr.Client/DaprClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public abstract class DaprClient : IDisposable
/// <param name="appId">
/// An optional <c>app-id</c>. If specified, the <c>app-id</c> will be configured as the value of
/// <see cref="HttpClient.BaseAddress" /> so that relative URIs can be used.
/// If specified, the client could not call different services.
/// </param>
/// <param name="daprEndpoint">The HTTP endpoint of the Dapr process to use for service invocation calls.</param>
/// <param name="daprApiToken">The token to be added to all request headers to Dapr runtime.</param>
Expand All @@ -79,7 +80,8 @@ public static HttpClient CreateInvokeHttpClient(string appId = null, string dapr
var handler = new InvocationHandler()
{
InnerHandler = new HttpClientHandler(),
DaprApiToken = daprApiToken
DaprApiToken = daprApiToken,
AppId = appId,
};

if (daprEndpoint is string)
Expand Down
18 changes: 16 additions & 2 deletions src/Dapr.Client/InvocationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ public string DaprEndpoint
}
}

/// <summary>
/// Gets or sets the AppId used for service invocation
/// </summary>
/// <returns>The AppId used for service invocation</returns>
public string? AppId { get; set; }

// Internal for testing
internal string? DaprApiToken
{
Expand Down Expand Up @@ -130,12 +136,20 @@ internal bool TryRewriteUri(Uri? uri, [NotNullWhen(true)] out Uri? rewritten)
return false;
}

// If the URI has a host which does not correspond to the AppId, it does not make sense.
// We do this check for optimization, to not add some overhead time for the "normal" use case
if (this.AppId is not null && !this.AppId.Equals(uri.Host, StringComparison.CurrentCultureIgnoreCase))
{
rewritten = null;
return false;
}

var builder = new UriBuilder(uri)
{
Scheme = this.parsedEndpoint.Scheme,
Host = this.parsedEndpoint.Host,
Port = this.parsedEndpoint.Port,
Path = $"/v1.0/invoke/{this.GetOriginalHostFromUri(uri)}/method" + uri.AbsolutePath,
Path = $"/v1.0/invoke/{this.AppId ?? this.GetOriginalHostFromUri(uri)}/method" + uri.AbsolutePath,
};

rewritten = builder.Uri;
Expand All @@ -144,7 +158,7 @@ internal bool TryRewriteUri(Uri? uri, [NotNullWhen(true)] out Uri? rewritten)

/// <summary>
/// Get the original host (case sensitive) from the URI (thanks to uri.OriginalString)
/// Mandatory to get the original host if the app id has at least one uppercase
/// Mandatory to get the original host if the app id has at least one uppercase and the app id has not been sent to the handler
/// </summary>
/// <param name="uri">The uri</param>
/// <returns>The original hostname from the uri</returns>
Expand Down
2 changes: 1 addition & 1 deletion test/Dapr.Client.Test/DaprClientTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down
79 changes: 65 additions & 14 deletions test/Dapr.Client.Test/InvocationHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,31 +79,44 @@ public void TryRewriteUri_FailsForRelativeUris()
}

[Theory]
[InlineData("http://bank", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData("http://Bank", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData("http://bank:3939", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData("http://Bank:3939", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData("http://app-id.with.dots", "https://some.host:3499/v1.0/invoke/app-id.with.dots/method/")]
[InlineData("http://App-id.with.dots", "https://some.host:3499/v1.0/invoke/App-id.with.dots/method/")]
[InlineData("http://bank:3939/", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData("http://Bank:3939/", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData("http://bank:3939/some/path", "https://some.host:3499/v1.0/invoke/bank/method/some/path")]
[InlineData("http://Bank:3939/some/path", "https://some.host:3499/v1.0/invoke/Bank/method/some/path")]
[InlineData("http://bank:3939/some/path?q=test&p=another#fragment", "https://some.host:3499/v1.0/invoke/bank/method/some/path?q=test&p=another#fragment")]
[InlineData("http://Bank:3939/some/path?q=test&p=another#fragment", "https://some.host:3499/v1.0/invoke/Bank/method/some/path?q=test&p=another#fragment")]
public void TryRewriteUri_RewritesUriToDaprInvoke(string uri, string expected)
[InlineData(null, "http://bank", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData("bank", "http://bank", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData(null, "http://Bank", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData("Bank", "http://Bank", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData(null, "http://bank:3939", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData("bank", "http://bank:3939", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData(null, "http://Bank:3939", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData("Bank", "http://Bank:3939", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData(null, "http://app-id.with.dots", "https://some.host:3499/v1.0/invoke/app-id.with.dots/method/")]
[InlineData("app-id.with.dots", "http://app-id.with.dots", "https://some.host:3499/v1.0/invoke/app-id.with.dots/method/")]
[InlineData(null, "http://App-id.with.dots", "https://some.host:3499/v1.0/invoke/App-id.with.dots/method/")]
[InlineData("App-id.with.dots", "http://App-id.with.dots", "https://some.host:3499/v1.0/invoke/App-id.with.dots/method/")]
[InlineData(null, "http://bank:3939/", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData("bank", "http://bank:3939/", "https://some.host:3499/v1.0/invoke/bank/method/")]
[InlineData(null, "http://Bank:3939/", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData("Bank", "http://Bank:3939/", "https://some.host:3499/v1.0/invoke/Bank/method/")]
[InlineData(null, "http://bank:3939/some/path", "https://some.host:3499/v1.0/invoke/bank/method/some/path")]
[InlineData("bank", "http://bank:3939/some/path", "https://some.host:3499/v1.0/invoke/bank/method/some/path")]
[InlineData(null, "http://Bank:3939/some/path", "https://some.host:3499/v1.0/invoke/Bank/method/some/path")]
[InlineData("Bank", "http://Bank:3939/some/path", "https://some.host:3499/v1.0/invoke/Bank/method/some/path")]
[InlineData(null, "http://bank:3939/some/path?q=test&p=another#fragment", "https://some.host:3499/v1.0/invoke/bank/method/some/path?q=test&p=another#fragment")]
[InlineData("bank", "http://bank:3939/some/path?q=test&p=another#fragment", "https://some.host:3499/v1.0/invoke/bank/method/some/path?q=test&p=another#fragment")]
[InlineData(null, "http://Bank:3939/some/path?q=test&p=another#fragment", "https://some.host:3499/v1.0/invoke/Bank/method/some/path?q=test&p=another#fragment")]
[InlineData("Bank", "http://Bank:3939/some/path?q=test&p=another#fragment", "https://some.host:3499/v1.0/invoke/Bank/method/some/path?q=test&p=another#fragment")]
public void TryRewriteUri_WithNoAppId_RewritesUriToDaprInvoke(string? appId, string uri, string expected)
{
var handler = new InvocationHandler()
{
DaprEndpoint = "https://some.host:3499",
AppId = appId,
};

Assert.True(handler.TryRewriteUri(new Uri(uri), out var rewritten));
Assert.Equal(expected, rewritten!.OriginalString);
}

[Fact]
public async Task SendAsync_InvalidUri_ThrowsException()
public async Task SendAsync_InvalidNotSetUri_ThrowsException()
{
var handler = new InvocationHandler();
var ex = await Assert.ThrowsAsync<ArgumentException>(async () =>
Expand All @@ -114,6 +127,19 @@ public async Task SendAsync_InvalidUri_ThrowsException()
Assert.Contains("The request URI '' is not a valid Dapr service invocation destination.", ex.Message);
}

[Fact]
public async Task SendAsync_InvalidUriWithAppId_ThrowsException()
{
var handler = new InvocationHandler() { AppId = "bank" };
string fakeUrl = "http://invalid/test";
var ex = await Assert.ThrowsAsync<ArgumentException>(async () =>
{
await CallSendAsync(handler, new HttpRequestMessage() { RequestUri = new Uri(fakeUrl) }); // No URI set
});

Assert.Contains($"The request URI '{fakeUrl}' is not a valid Dapr service invocation destination.", ex.Message);
}

[Fact]
public async Task SendAsync_RewritesUri()
{
Expand All @@ -138,6 +164,31 @@ public async Task SendAsync_RewritesUri()
Assert.False(request.Headers.TryGetValues("dapr-api-token", out _));
}

[Fact]
public async Task SendAsync_RewritesUri_AndAppId()
{
var uri = "http://bank/accounts/17?";

var capture = new CaptureHandler();
var handler = new InvocationHandler()
{
InnerHandler = capture,

DaprEndpoint = "https://localhost:5000",
DaprApiToken = null,
AppId = "bank"
};

var request = new HttpRequestMessage(HttpMethod.Post, uri);
var response = await CallSendAsync(handler, request);

Assert.Equal("https://localhost:5000/v1.0/invoke/bank/method/accounts/17?", capture.RequestUri?.OriginalString);
Assert.Null(capture.DaprApiToken);

Assert.Equal(uri, request.RequestUri?.OriginalString);
Assert.False(request.Headers.TryGetValues("dapr-api-token", out _));
}

[Fact]
public async Task SendAsync_RewritesUri_AndAddsApiToken()
{
Expand Down

0 comments on commit 07a75f3

Please sign in to comment.