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
2 changes: 1 addition & 1 deletion src/NATS.Client.Core/Internal/UserCredentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ internal async Task AuthenticateAsync(ClientOpts opts, ServerInfo? info, NatsUri
using var reader = new StreamReader(path);
return ParseCreds(reader);
}
catch (NatsException e)
catch (Exception e)
{
throw new NatsException($"Error loading creds file '{path}': {e.Message}", e);
}
Expand Down
21 changes: 19 additions & 2 deletions src/NATS.Client.Core/NatsConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -394,9 +394,26 @@ private async ValueTask InitialConnectAsync()
throw new NatsException($"URI {uri} requires TLS but TlsMode is set to Disable");
}

if (!Opts.AuthOpts.IsAnonymous)
try
{
if (!Opts.AuthOpts.IsAnonymous)
{
_userCredentials = new UserCredentials(Opts.AuthOpts);
}
}
catch (Exception ex)
{
_userCredentials = new UserCredentials(Opts.AuthOpts);
var exception = ex as NatsException ?? new NatsException($"Failed to load credentials: {ex.Message}", ex);
lock (_gate)
{
ConnectionState = NatsConnectionState.Closed; // allow retry connect

// throw for the waiter
_waitForOpenConnection.TrySetObservedException(exception);
_waitForOpenConnection = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
}

throw exception;
}

var attemptedUris = new List<NatsUri>();
Expand Down
27 changes: 27 additions & 0 deletions tests/NATS.Client.CoreUnit.Tests/NatsConnectionAuthTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace NATS.Client.CoreUnit.Tests;

public class NatsConnectionAuthTests
{
[Fact]
public async Task ConnectAsync_MissingCredsFile_SecondCallDoesNotHang()
{
var missingPath = Path.Combine(Path.GetTempPath(), $"nats-missing-{Guid.NewGuid():N}.creds");
var opts = NatsOpts.Default with
{
Url = "nats://127.0.0.1:4222",
RetryOnInitialConnect = false,
AuthOpts = NatsAuthOpts.Default with { CredsFile = missingPath },
};

await using var nats = new NatsConnection(opts);

var first = async () => await nats.ConnectAsync();
await first.Should().ThrowAsync<NatsException>();

var secondTask = nats.ConnectAsync().AsTask();
var completed = await Task.WhenAny(secondTask, Task.Delay(TimeSpan.FromSeconds(5)));
completed.Should().BeSameAs(secondTask, "second ConnectAsync must not hang");
var second = async () => await secondTask;
await second.Should().ThrowAsync<NatsException>();
}
}
Loading