// Copyright © WireMock.Net
using System;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Client.Builders;
namespace WireMock.Client.Extensions;
///
/// Some extensions for .
///
public static class WireMockAdminApiExtensions
{
private const int MaxRetries = 5;
private const int InitialWaitingTimeInMilliSeconds = 500;
private const string HealthStatusHealthy = "Healthy";
///
/// Get a new for the .
///
/// See .
///
public static AdminApiMappingBuilder GetMappingBuilder(this IWireMockAdminApi adminApi)
{
return new AdminApiMappingBuilder(adminApi);
}
///
/// Set basic authentication to access the .
///
/// See .
/// The admin username.
/// The admin password.
///
public static IWireMockAdminApi WithAuthorization(this IWireMockAdminApi adminApi, string username, string password)
{
Guard.NotNull(adminApi);
Guard.NotNullOrEmpty(username);
Guard.NotNullOrEmpty(password);
adminApi.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}")));
return adminApi;
}
///
/// Wait for the WireMock.Net server to be healthy. (The "/__admin/health" returns "Healthy").
///
/// See .
/// The maximum number of retries. Default is 5.
/// The optional .
/// A completed Task in case the health endpoint is available, else throws a .
public static async Task WaitForHealthAsync(this IWireMockAdminApi adminApi, int maxRetries = MaxRetries, CancellationToken cancellationToken = default)
{
Guard.NotNull(adminApi);
var retries = 0;
var waitTime = InitialWaitingTimeInMilliSeconds;
var totalWaitTime = waitTime;
var isHealthy = await IsHealthyAsync(adminApi, cancellationToken);
while (!isHealthy && retries < MaxRetries && !cancellationToken.IsCancellationRequested)
{
waitTime = (int)(InitialWaitingTimeInMilliSeconds * Math.Pow(2, retries));
await Task.Delay(waitTime, cancellationToken);
isHealthy = await IsHealthyAsync(adminApi, cancellationToken);
retries++;
totalWaitTime += waitTime;
}
if (retries >= MaxRetries)
{
throw new InvalidOperationException($"The /__admin/health endpoint did not return 'Healthy' after {MaxRetries} retries and {totalWaitTime / 1000.0:0.0} seconds.");
}
}
private static async Task IsHealthyAsync(IWireMockAdminApi adminApi, CancellationToken cancellationToken)
{
try
{
var status = await adminApi.GetHealthAsync(cancellationToken);
return string.Equals(status, HealthStatusHealthy, StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
}
}