using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using DotNet.Testcontainers.Containers;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using RestEase;
using Stef.Validation;
using WireMock.Client;
namespace WireMock.Net.Testcontainers;
///
/// A container for running WireMock in a docker environment.
///
public sealed class WireMockContainer : DockerContainer
{
internal const int ContainerPort = 80;
private readonly WireMockConfiguration _configuration;
///
/// Initializes a new instance of the class.
///
/// The container configuration.
/// The logger.
public WireMockContainer(WireMockConfiguration configuration, ILogger logger) : base(configuration, logger)
{
_configuration = Guard.NotNull(configuration);
}
///
/// Gets the public Url.
///
[PublicAPI]
public string GetPublicUrl() => GetPublicUri().ToString();
///
/// Create a RestEase Admin client which can be used to call the admin REST endpoint.
///
/// A
[PublicAPI]
public IWireMockAdminApi CreateWireMockAdminClient()
{
ValidateIfRunning();
var api = RestClient.For(GetPublicUri());
if (_configuration.HasBasicAuthentication)
{
api.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_configuration.Username}:{_configuration.Password}")));
}
return api;
}
///
/// Create a which can be used to call this instance.
///
/// An ordered list of System.Net.Http.DelegatingHandler instances to be invoked
/// as an System.Net.Http.HttpRequestMessage travels from the System.Net.Http.HttpClient
/// to the network and an System.Net.Http.HttpResponseMessage travels from the network
/// back to System.Net.Http.HttpClient. The handlers are invoked in a top-down fashion.
/// That is, the first entry is invoked first for an outbound request message but
/// last for an inbound response message.
///
///
[PublicAPI]
public HttpClient CreateClient(params DelegatingHandler[] handlers)
{
ValidateIfRunning();
var client = HttpClientFactory.Create(handlers);
client.BaseAddress = GetPublicUri();
return client;
}
///
/// Create a (one for each URL) which can be used to call this instance.
/// The inner handler represents the destination of the HTTP message channel.
///
/// An ordered list of System.Net.Http.DelegatingHandler instances to be invoked
/// as an System.Net.Http.HttpRequestMessage travels from the System.Net.Http.HttpClient
/// to the network and an System.Net.Http.HttpResponseMessage travels from the network
/// back to System.Net.Http.HttpClient. The handlers are invoked in a top-down fashion.
/// That is, the first entry is invoked first for an outbound request message but
/// last for an inbound response message.
///
///
[PublicAPI]
public HttpClient CreateClient(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers)
{
ValidateIfRunning();
var client = HttpClientFactory.Create(innerHandler, handlers);
client.BaseAddress = GetPublicUri();
return client;
}
private void ValidateIfRunning()
{
if (State != TestcontainersStates.Running)
{
throw new InvalidOperationException("Unable to create HttpClient because the WireMock.Net is not yet running.");
}
}
private Uri GetPublicUri() => new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(ContainerPort)).Uri;
}