Skip to content
Merged
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
35 changes: 18 additions & 17 deletions src/NATS.Client.Core/Internal/NatsUri.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ internal sealed record NatsUri
{
public const string DefaultScheme = "nats";

private readonly string _redacted;

public NatsUri(string urlString, bool isSeed, string defaultScheme = DefaultScheme)
{
IsSeed = isSeed;
Expand Down Expand Up @@ -40,6 +38,23 @@ public NatsUri(string urlString, bool isSeed, string defaultScheme = DefaultSche
}

Uri = uriBuilder.Uri;
}

public Uri Uri { get; init; }

public bool IsSeed { get; }

public bool IsTls { get; }

public bool IsWebSocket { get; }

public string Host => Uri.Host;

public int Port => Uri.Port;

public override string ToString()
{
var uriBuilder = new UriBuilder(Uri);

// Redact user/password or token from the URI string for logging
if (uriBuilder.UserName is { Length: > 0 })
Expand All @@ -54,20 +69,6 @@ public NatsUri(string urlString, bool isSeed, string defaultScheme = DefaultSche
}
}

_redacted = IsWebSocket && Uri.AbsolutePath != "/" ? uriBuilder.Uri.ToString() : uriBuilder.Uri.ToString().Trim('/');
return IsWebSocket && Uri.AbsolutePath != "/" ? uriBuilder.Uri.ToString() : uriBuilder.Uri.ToString().Trim('/');
}

public Uri Uri { get; init; }

public bool IsSeed { get; }

public bool IsTls { get; }

public bool IsWebSocket { get; }

public string Host => Uri.Host;

public int Port => Uri.Port;

public override string ToString() => _redacted;
}
32 changes: 32 additions & 0 deletions tests/NATS.Client.Core2.Tests/OnConnectingUriTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Microsoft.Extensions.Logging;
using NATS.Client.Platform.Windows.Tests;
using NATS.Client.TestUtilities;

namespace NATS.Client.Core2.Tests;

public class OnConnectingUriTest(ITestOutputHelper output)
{
[Fact]
public async Task Logs_show_overridden_uri_when_OnConnectingAsync_changes_host_port()
{
await using var server = await NatsServerProcess.StartAsync();
var serverPort = server.Port;

var logger = new InMemoryTestLoggerFactory(LogLevel.Information, m => output.WriteLine($"LOG: {m.Message}"));

await using var nats = new NatsConnection(new NatsOpts
{
Url = "nats://original-host:4222",
LoggerFactory = logger,
});

nats.OnConnectingAsync = _ => new ValueTask<(string Host, int Port)>(("127.0.0.1", serverPort));

await nats.ConnectAsync();

var connectLog = logger.Logs.FirstOrDefault(m => m.Message.Contains("Connect to NATS using"));
Assert.NotNull(connectLog);
Assert.Contains($"127.0.0.1:{serverPort}", connectLog.Message);
Assert.DoesNotContain("original-host", connectLog.Message);
}
}
20 changes: 20 additions & 0 deletions tests/NATS.Client.CoreUnit.Tests/OptsUrlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,25 @@ public void Keep_URL_wss_path_and_query_string()
Assert.Equal("t,", opts.AuthOpts.Token);
}

[Fact]
public void ToString_reflects_uri_changed_via_with_expression()
{
var original = new NatsUri("host1:4222", true);
Assert.Equal("nats://host1:4222", original.ToString());

var modified = original with { Uri = new UriBuilder(original.Uri) { Host = "host2", Port = 5222 }.Uri };
Assert.Equal("nats://host2:5222", modified.ToString());
}

[Fact]
public void ToString_reflects_uri_changed_via_with_expression_redacted()
{
var original = new NatsUri("u:p@host1:4222", true);
Assert.Equal("nats://u:***@host1:4222", original.ToString());

var modified = original with { Uri = new UriBuilder(original.Uri) { Host = "host2", Port = 5222 }.Uri };
Assert.Equal("nats://u:***@host2:5222", modified.ToString());
}

private static string GetUrisAsRedactedString(NatsOpts opts) => string.Join(",", opts.GetSeedUris(true).Select(u => u.ToString()));
}
Loading