You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.5 KiB
104 lines
3.5 KiB
#nullable enable |
|
|
|
using System.Net; |
|
|
|
namespace Bit.Test.Common.MockedHttpClient; |
|
|
|
public class HttpRequestMatcher : IHttpRequestMatcher |
|
{ |
|
private readonly Func<HttpRequestMessage, bool> _matcher; |
|
private HttpRequestMatcher? _childMatcher; |
|
private MockedHttpResponse _mockedResponse = new(HttpStatusCode.OK); |
|
private bool _responseSpecified = false; |
|
|
|
public int NumberOfMatches { get; private set; } |
|
|
|
/// <summary> |
|
/// Returns whether or not the provided request can be handled by this matcher chain. |
|
/// </summary> |
|
/// <param name="request"></param> |
|
/// <returns></returns> |
|
public bool Matches(HttpRequestMessage request) => _matcher(request) && (_childMatcher == null || _childMatcher.Matches(request)); |
|
|
|
public HttpRequestMatcher(HttpMethod method) |
|
{ |
|
_matcher = request => request.Method == method; |
|
} |
|
|
|
public HttpRequestMatcher(string uri) |
|
{ |
|
_matcher = request => request.RequestUri == new Uri(uri); |
|
} |
|
|
|
public HttpRequestMatcher(Uri uri) |
|
{ |
|
_matcher = request => request.RequestUri == uri; |
|
} |
|
|
|
public HttpRequestMatcher(HttpMethod method, string uri) |
|
{ |
|
_matcher = request => request.Method == method && request.RequestUri == new Uri(uri); |
|
} |
|
|
|
public HttpRequestMatcher(Func<HttpRequestMessage, bool> matcher) |
|
{ |
|
_matcher = matcher; |
|
} |
|
|
|
public HttpRequestMatcher WithHeader(string name, string value) |
|
{ |
|
return AddChild(request => request.Headers.TryGetValues(name, out var values) && values.Contains(value)); |
|
} |
|
|
|
public HttpRequestMatcher WithQueryParameters(Dictionary<string, string> requiredQueryParameters) => |
|
WithQueryParameters(requiredQueryParameters.Select(x => $"{x.Key}={x.Value}").ToArray()); |
|
public HttpRequestMatcher WithQueryParameters(string name, string value) => |
|
WithQueryParameters($"{name}={value}"); |
|
public HttpRequestMatcher WithQueryParameters(params string[] queryKeyValues) |
|
{ |
|
bool matcher(HttpRequestMessage request) |
|
{ |
|
var query = request.RequestUri?.Query; |
|
if (query == null) |
|
{ |
|
return false; |
|
} |
|
|
|
return queryKeyValues.All(queryKeyValue => query.Contains(queryKeyValue)); |
|
} |
|
return AddChild(matcher); |
|
} |
|
|
|
/// <summary> |
|
/// Configure how this matcher should respond to matching HttpRequestMessages. |
|
/// Note, after specifying a response, you can no longer further specify match criteria. |
|
/// </summary> |
|
/// <param name="statusCode"></param> |
|
/// <returns></returns> |
|
public MockedHttpResponse RespondWith(HttpStatusCode statusCode) |
|
{ |
|
_responseSpecified = true; |
|
_mockedResponse = new MockedHttpResponse(statusCode); |
|
return _mockedResponse; |
|
} |
|
|
|
/// <summary> |
|
/// Called to produce an HttpResponseMessage for the given request. This is probably something you want to leave alone |
|
/// </summary> |
|
/// <param name="request"></param> |
|
public async Task<HttpResponseMessage> RespondToAsync(HttpRequestMessage request) |
|
{ |
|
NumberOfMatches++; |
|
return await (_childMatcher == null ? _mockedResponse.RespondToAsync(request) : _childMatcher.RespondToAsync(request)); |
|
} |
|
|
|
private HttpRequestMatcher AddChild(Func<HttpRequestMessage, bool> matcher) |
|
{ |
|
if (_responseSpecified) |
|
{ |
|
throw new Exception("Cannot continue to configure a matcher after a response has been specified"); |
|
} |
|
_childMatcher = new HttpRequestMatcher(matcher); |
|
return _childMatcher; |
|
} |
|
}
|
|
|