Skip to content

Commit

Permalink
✨ Added Basic Http Wait Options
Browse files Browse the repository at this point in the history
  • Loading branch information
Alfred Neequaye committed Dec 2, 2022
1 parent 0bae84b commit 011ae92
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/Testcontainers/Configurations/UntilHttpOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#nullable enable
namespace DotNet.Testcontainers.Configurations
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Security;

public class UntilHttpOptions
{
public UntilHttpOptions()
{
this.Method = HttpMethod.Get;
this.Path = "/";
this.Host = "localhost";
this.Port = 80;
this.ExpectedResponseCodes = new() { HttpStatusCode.OK };
this.TimeOut = TimeSpan.FromMinutes(1);
this.RequestDelay = 1;
}

public HttpMethod Method { get; set; }
public string Path { get; set; }
public string Host { get; set; }
public int Port { get; set; }
public HashSet<HttpStatusCode> ExpectedResponseCodes { get; set; }
public string? ExpectedOutput { get; set; }
public HttpContent? RequestContent { get; set; }
public bool UseSecure { get; set; }
public SecureString? AuthString { get; set; }
public bool UseAuth { get; set; }
public TimeSpan TimeOut { get; set; }
public bool ValidateContent { get; set; }
public double RequestDelay { get; set; }

public Uri Uri => new($"{(this.UseSecure ? "https" : "http")}://{this.Host}:{this.Port}{this.Path}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ public interface IWaitForContainerOS
[PublicAPI]
IWaitForContainerOS UntilContainerIsHealthy(long failingStreak = 20);

/// <summary>
/// Waits until Http Requests returns Ok
/// </summary>
/// <returns>A configured instance of <see cref="IWaitForContainerOS" />.</returns>
[PublicAPI]
IWaitForContainerOS UntilHttpSuccess(Action<UntilHttpOptions>? action = null);

/// <summary>
/// Returns a collection with all configured wait strategies.
/// </summary>
Expand Down
66 changes: 66 additions & 0 deletions src/Testcontainers/Configurations/WaitStrategies/UntilHttp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace DotNet.Testcontainers.Configurations
{
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using DotNet.Testcontainers.Containers;
using Microsoft.Extensions.Logging;

public class UntilHttp : IWaitUntil
{
private readonly UntilHttpOptions Options;

public UntilHttp(string path)
{
this.Options = new() { Path = path, Method = HttpMethod.Get };
}

public UntilHttp(UntilHttpOptions options)
{
this.Options = options;
}

public async Task<bool> Until(ITestcontainersContainer testcontainers, ILogger logger)
{
var mappedPort = testcontainers.GetMappedPublicPort(this.Options.Port);
this.Options.Port = mappedPort;
var client = new HttpClient();
var message = new HttpRequestMessage(this.Options.Method, this.Options.Uri);
if (this.Options.RequestContent is not null && (this.Options.Method == HttpMethod.Post || this.Options.Method == HttpMethod.Put))
{
message.Content = this.Options.RequestContent;
}

if (this.Options.UseAuth && this.Options.AuthString is not null)
{
message.Headers.Authorization = AuthenticationHeaderValue.Parse(this.Options.AuthString.ToString());
}

var sendTask = Task.Run(async () =>
{
HttpResponseMessage response = null;
while (response is null || !this.Options.ExpectedResponseCodes.Contains(response.StatusCode))
{
response = await client.SendAsync(message);
if (!this.Options.ExpectedResponseCodes.Contains(response.StatusCode))
{
Thread.Sleep(TimeSpan.FromSeconds(this.Options.RequestDelay));
}
}

return response;
});
var completed = sendTask.Wait(this.Options.TimeOut);
if (!completed)
{
return false;
}

var responseContent = await sendTask.Result.Content.ReadAsStringAsync();
return !this.Options.ValidateContent || Regex.Match(this.Options.ExpectedOutput, responseContent).Success;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ public virtual IWaitForContainerOS UntilContainerIsHealthy(long failingStreak =
return this.AddCustomWaitStrategy(new UntilContainerIsHealthy(failingStreak));
}

/// <inheritdoc />
public IWaitForContainerOS UntilHttpSuccess(Action<UntilHttpOptions> action = null)
{
var options = new UntilHttpOptions();
action?.Invoke(options);
var httpWait = new UntilHttp(options);
return this.AddCustomWaitStrategy(httpWait);
}

/// <inheritdoc />
public IEnumerable<IWaitUntil> Build()
{
Expand Down
1 change: 1 addition & 0 deletions src/Testcontainers/Testcontainers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
<RootNamespace>DotNet.Testcontainers</RootNamespace>
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" />
Expand Down

0 comments on commit 011ae92

Please sign in to comment.