// 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; } } }