From 139ea77888c016bfef0886c77b2b833f5b4800a7 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Mon, 18 Sep 2017 20:01:38 +0200 Subject: [PATCH] Add ClientIP to RequestMessage / RequestLog (#46) --- .../WireMock.Net.StandAlone.NETCoreApp.csproj | 3 +- .../run1.cmd | 1 + .../run2.cmd | 1 + .../Admin/Mappings/ClientIPModel.cs | 24 +++ .../Admin/Mappings/RequestModel.cs | 10 +- .../Admin/Requests/LogRequestModel.cs | 5 + src/WireMock.Net/Matchers/MatchScores.cs | 10 +- .../Request/RequestMessageClientIPMatcher.cs | 81 ++++++++++ .../Request/RequestMessageCompositeMatcher.cs | 5 + .../Request/RequestMessageUrlMatcher.cs | 4 +- src/WireMock.Net/Owin/OwinRequestMapper.cs | 141 +++++++++--------- .../IClientIPRequestBuilder.cs | 33 ++++ .../RequestBuilders/IRequestBuilder.cs | 2 +- src/WireMock.Net/RequestBuilders/Request.cs | 39 +++++ src/WireMock.Net/RequestMessage.cs | 20 ++- .../Serialization/MappingConverter.cs | 8 +- .../Server/FluentMockServer.Admin.cs | 18 +++ .../WireMock.Net.Tests/RequestMessageTests.cs | 8 +- .../RequestTests.ClientIP.cs | 41 +++++ test/WireMock.Net.Tests/RequestTests.cs | 76 +++++----- test/WireMock.Net.Tests/ResponseTests.cs | 16 +- .../WireMock.Net.Tests.csproj | 2 +- 22 files changed, 414 insertions(+), 134 deletions(-) create mode 100644 examples/WireMock.Net.StandAlone.NETCoreApp/run1.cmd create mode 100644 examples/WireMock.Net.StandAlone.NETCoreApp/run2.cmd create mode 100644 src/WireMock.Net/Admin/Mappings/ClientIPModel.cs create mode 100644 src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs create mode 100644 src/WireMock.Net/RequestBuilders/IClientIPRequestBuilder.cs create mode 100644 test/WireMock.Net.Tests/RequestTests.ClientIP.cs diff --git a/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj b/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj index 24dd3352..17a7b614 100644 --- a/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj +++ b/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj @@ -2,8 +2,7 @@ Exe - netcoreapp1.0;netcoreapp2.0 - + netcoreapp1.1;netcoreapp2.0 ../../WireMock.Net-Logo.ico diff --git a/examples/WireMock.Net.StandAlone.NETCoreApp/run1.cmd b/examples/WireMock.Net.StandAlone.NETCoreApp/run1.cmd new file mode 100644 index 00000000..53bd1ff5 --- /dev/null +++ b/examples/WireMock.Net.StandAlone.NETCoreApp/run1.cmd @@ -0,0 +1 @@ +dotnet run --framework netcoreapp1.1 \ No newline at end of file diff --git a/examples/WireMock.Net.StandAlone.NETCoreApp/run2.cmd b/examples/WireMock.Net.StandAlone.NETCoreApp/run2.cmd new file mode 100644 index 00000000..ce2e3e04 --- /dev/null +++ b/examples/WireMock.Net.StandAlone.NETCoreApp/run2.cmd @@ -0,0 +1 @@ +dotnet run --framework netcoreapp2.0 \ No newline at end of file diff --git a/src/WireMock.Net/Admin/Mappings/ClientIPModel.cs b/src/WireMock.Net/Admin/Mappings/ClientIPModel.cs new file mode 100644 index 00000000..4a04448a --- /dev/null +++ b/src/WireMock.Net/Admin/Mappings/ClientIPModel.cs @@ -0,0 +1,24 @@ +namespace WireMock.Admin.Mappings +{ + /// + /// ClientIPModel + /// + public class ClientIPModel + { + /// + /// Gets or sets the matchers. + /// + /// + /// The matchers. + /// + public MatcherModel[] Matchers { get; set; } + + /// + /// Gets or sets the functions. + /// + /// + /// The functions. + /// + public string[] Funcs { get; set; } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Admin/Mappings/RequestModel.cs b/src/WireMock.Net/Admin/Mappings/RequestModel.cs index 24880c97..84c8fb1c 100644 --- a/src/WireMock.Net/Admin/Mappings/RequestModel.cs +++ b/src/WireMock.Net/Admin/Mappings/RequestModel.cs @@ -7,11 +7,19 @@ namespace WireMock.Admin.Mappings /// public class RequestModel { + /// + /// Gets or sets the ClientIP. (Can be a string or a ClientIPModel) + /// + /// + /// The ClientIP. + /// + public object ClientIP { get; set; } + /// /// Gets or sets the Path. (Can be a string or a PathModel) /// /// - /// The URL. + /// The Path. /// public object Path { get; set; } diff --git a/src/WireMock.Net/Admin/Requests/LogRequestModel.cs b/src/WireMock.Net/Admin/Requests/LogRequestModel.cs index 7a74a098..77a97b78 100644 --- a/src/WireMock.Net/Admin/Requests/LogRequestModel.cs +++ b/src/WireMock.Net/Admin/Requests/LogRequestModel.cs @@ -10,6 +10,11 @@ namespace WireMock.Admin.Requests /// public class LogRequestModel { + /// + /// Gets the Client IP Address. + /// + public string ClientIP { get; set; } + /// /// Gets the DateTime. /// diff --git a/src/WireMock.Net/Matchers/MatchScores.cs b/src/WireMock.Net/Matchers/MatchScores.cs index 5304ba88..789a810a 100644 --- a/src/WireMock.Net/Matchers/MatchScores.cs +++ b/src/WireMock.Net/Matchers/MatchScores.cs @@ -37,22 +37,20 @@ namespace WireMock.Matchers /// Calculates the score from multiple funcs. /// /// The values. - /// score + /// average score public static double ToScore(IEnumerable values) { - var list = values.Select(ToScore).ToList(); - return list.Sum() / list.Count; + return values.Any() ? values.Select(ToScore).Average() : Mismatch; } /// /// Calculates the score from multiple funcs. /// /// The values. - /// score + /// average score public static double ToScore(IEnumerable values) { - var list = values.ToList(); - return list.Sum() / list.Count; + return values.Any() ? values.Average() : Mismatch; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs new file mode 100644 index 00000000..a20bc047 --- /dev/null +++ b/src/WireMock.Net/Matchers/Request/RequestMessageClientIPMatcher.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using WireMock.Validation; + +namespace WireMock.Matchers.Request +{ + /// + /// The request ClientIP matcher. + /// + public class RequestMessageClientIPMatcher : IRequestMatcher + { + /// + /// The matchers. + /// + public IReadOnlyList Matchers { get; } + + /// + /// The ClientIP functions. + /// + public Func[] Funcs { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The clientIPs. + public RequestMessageClientIPMatcher([NotNull] params string[] clientIPs) : this(clientIPs.Select(ip => new WildcardMatcher(ip)).ToArray()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The matchers. + public RequestMessageClientIPMatcher([NotNull] params IMatcher[] matchers) + { + Check.NotNull(matchers, nameof(matchers)); + Matchers = matchers; + } + + /// + /// Initializes a new instance of the class. + /// + /// The clientIP functions. + public RequestMessageClientIPMatcher([NotNull] params Func[] funcs) + { + Check.NotNull(funcs, nameof(funcs)); + Funcs = funcs; + } + + /// + /// Determines whether the specified RequestMessage is match. + /// + /// The RequestMessage. + /// The RequestMatchResult. + /// + /// A value between 0.0 - 1.0 of the similarity. + /// + public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult) + { + double score = IsMatch(requestMessage); + requestMatchResult.TotalScore += score; + + requestMatchResult.TotalNumber++; + + return score; + } + + private double IsMatch(RequestMessage requestMessage) + { + if (Matchers != null) + return Matchers.Max(matcher => matcher.IsMatch(requestMessage.ClientIP)); + + if (Funcs != null) + return MatchScores.ToScore(requestMessage.ClientIP != null && Funcs.Any(func => func(requestMessage.ClientIP))); + + return MatchScores.Mismatch; + } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs index 42a36022..4139f980 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageCompositeMatcher.cs @@ -43,6 +43,11 @@ namespace WireMock.Matchers.Request /// public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult) { + if (!RequestMatchers.Any()) + { + return MatchScores.Mismatch; + } + if (_type == CompositeMatcherType.And) { return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult)); diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs index e0af64d5..5f609a92 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs +++ b/src/WireMock.Net/Matchers/Request/RequestMessageUrlMatcher.cs @@ -12,12 +12,12 @@ namespace WireMock.Matchers.Request public class RequestMessageUrlMatcher : IRequestMatcher { /// - /// The matcher. + /// The matchers. /// public IReadOnlyList Matchers { get; } /// - /// The url functions + /// The url functions. /// public Func[] Funcs { get; } diff --git a/src/WireMock.Net/Owin/OwinRequestMapper.cs b/src/WireMock.Net/Owin/OwinRequestMapper.cs index c8e4ba81..4ccc3b9a 100644 --- a/src/WireMock.Net/Owin/OwinRequestMapper.cs +++ b/src/WireMock.Net/Owin/OwinRequestMapper.cs @@ -1,69 +1,74 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -#if !NETSTANDARD -using Microsoft.Owin; -#else -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -#endif - -namespace WireMock.Owin -{ - /// - /// OwinRequestMapper - /// - public class OwinRequestMapper - { - /// - /// MapAsync IOwinRequest to RequestMessage - /// - /// - /// - public async Task MapAsync( -#if !NETSTANDARD - IOwinRequest request -#else - HttpRequest request -#endif - ) - { -#if !NETSTANDARD - Uri url = request.Uri; -#else - Uri url = new Uri(request.GetEncodedUrl()); -#endif - string verb = request.Method; - - string bodyAsString = null; - byte[] body = null; - Encoding bodyEncoding = null; - if (request.Body != null) - { - using (var streamReader = new StreamReader(request.Body)) - { - bodyAsString = await streamReader.ReadToEndAsync(); - bodyEncoding = streamReader.CurrentEncoding; - } - - body = bodyEncoding.GetBytes(bodyAsString); - } - - var listenerHeaders = request.Headers; - - var headers = new Dictionary(); - foreach (var header in listenerHeaders) - headers.Add(header.Key, header.Value.FirstOrDefault()); - - var cookies = new Dictionary(); - - foreach (var cookie in request.Cookies) - cookies.Add(cookie.Key, cookie.Value); - - return new RequestMessage(url, verb, body, bodyAsString, bodyEncoding, headers, cookies) { DateTime = DateTime.Now }; - } - } +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +#if !NETSTANDARD +using Microsoft.Owin; +#else +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +#endif + +namespace WireMock.Owin +{ + /// + /// OwinRequestMapper + /// + public class OwinRequestMapper + { + /// + /// MapAsync IOwinRequest to RequestMessage + /// + /// + /// + public async Task MapAsync( +#if !NETSTANDARD + IOwinRequest request +#else + HttpRequest request +#endif + ) + { +#if !NETSTANDARD + Uri url = request.Uri; + string clientIP = request.RemoteIpAddress; +#else + Uri url = new Uri(request.GetEncodedUrl()); + var connection = request.HttpContext.Connection; + string clientIP = connection.RemoteIpAddress.IsIPv4MappedToIPv6 + ? connection.RemoteIpAddress.MapToIPv4().ToString() + : connection.RemoteIpAddress.ToString(); +#endif + string method = request.Method; + + string bodyAsString = null; + byte[] body = null; + Encoding bodyEncoding = null; + if (request.Body != null) + { + using (var streamReader = new StreamReader(request.Body)) + { + bodyAsString = await streamReader.ReadToEndAsync(); + bodyEncoding = streamReader.CurrentEncoding; + } + + body = bodyEncoding.GetBytes(bodyAsString); + } + + var listenerHeaders = request.Headers; + + var headers = new Dictionary(); + foreach (var header in listenerHeaders) + headers.Add(header.Key, header.Value.FirstOrDefault()); + + var cookies = new Dictionary(); + + foreach (var cookie in request.Cookies) + cookies.Add(cookie.Key, cookie.Value); + + return new RequestMessage(url, method, clientIP, body, bodyAsString, bodyEncoding, headers, cookies) { DateTime = DateTime.Now }; + } + } } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/IClientIPRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IClientIPRequestBuilder.cs new file mode 100644 index 00000000..c3257f84 --- /dev/null +++ b/src/WireMock.Net/RequestBuilders/IClientIPRequestBuilder.cs @@ -0,0 +1,33 @@ +using System; +using JetBrains.Annotations; +using WireMock.Matchers; + +namespace WireMock.RequestBuilders +{ + /// + /// The IClientIPRequestBuilder interface. + /// + public interface IClientIPRequestBuilder : IUrlAndPathRequestBuilder + { + /// + /// The with ClientIP. + /// + /// The matchers. + /// The . + IRequestBuilder WithClientIP([NotNull] params IMatcher[] matchers); + + /// + /// The with ClientIP. + /// + /// The clientIPs. + /// The . + IRequestBuilder WithClientIP([NotNull] params string[] clientIPs); + + /// + /// The with ClientIP. + /// + /// The path funcs. + /// The . + IRequestBuilder WithClientIP([NotNull] params Func[] funcs); + } +} \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs index 5dbd78e6..3662a38a 100644 --- a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs @@ -3,7 +3,7 @@ /// /// IRequestBuilder /// - public interface IRequestBuilder : IUrlAndPathRequestBuilder + public interface IRequestBuilder : IClientIPRequestBuilder { } } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.cs b/src/WireMock.Net/RequestBuilders/Request.cs index 144a2adf..ec87c1d6 100644 --- a/src/WireMock.Net/RequestBuilders/Request.cs +++ b/src/WireMock.Net/RequestBuilders/Request.cs @@ -54,6 +54,45 @@ namespace WireMock.RequestBuilders return _requestMatchers.Where(rm => rm is T).Cast().FirstOrDefault(); } + /// + /// The with clientIP. + /// + /// The matchers. + /// The . + public IRequestBuilder WithClientIP(params IMatcher[] matchers) + { + Check.NotEmpty(matchers, nameof(matchers)); + + _requestMatchers.Add(new RequestMessageClientIPMatcher(matchers)); + return this; + } + + /// + /// The with clientIP. + /// + /// The ClientIPs. + /// The . + public IRequestBuilder WithClientIP(params string[] clientIPs) + { + Check.NotEmpty(clientIPs, nameof(clientIPs)); + + _requestMatchers.Add(new RequestMessageClientIPMatcher(clientIPs)); + return this; + } + + /// + /// The with clientIP. + /// + /// The clientIP funcs. + /// The . + public IRequestBuilder WithClientIP(params Func[] funcs) + { + Check.NotEmpty(funcs, nameof(funcs)); + + _requestMatchers.Add(new RequestMessageClientIPMatcher(funcs)); + return this; + } + /// /// The with path. /// diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs index ba22fbb7..7ac655d4 100644 --- a/src/WireMock.Net/RequestMessage.cs +++ b/src/WireMock.Net/RequestMessage.cs @@ -13,6 +13,11 @@ namespace WireMock /// public class RequestMessage { + /// + /// Gets the Client IP Address. + /// + public string ClientIP { get; } + /// /// Gets the url. /// @@ -67,20 +72,23 @@ namespace WireMock /// Initializes a new instance of the class. /// /// The original url. - /// The verb. + /// The HTTP method. + /// The client IP Address. /// The bodyAsBytes byte[]. /// The body string. /// The body encoding /// The headers. /// The cookies. - public RequestMessage([NotNull] Uri url, [NotNull] string verb, [CanBeNull] byte[] bodyAsBytes = null, [CanBeNull] string body = null, [CanBeNull] Encoding bodyEncoding = null, [CanBeNull] IDictionary headers = null, [CanBeNull] IDictionary cookies = null) + public RequestMessage([NotNull] Uri url, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] byte[] bodyAsBytes = null, [CanBeNull] string body = null, [CanBeNull] Encoding bodyEncoding = null, [CanBeNull] IDictionary headers = null, [CanBeNull] IDictionary cookies = null) { Check.NotNull(url, nameof(url)); - Check.NotNull(verb, nameof(verb)); + Check.NotNull(method, nameof(method)); + Check.NotNull(clientIP, nameof(clientIP)); Url = url.ToString(); Path = url.AbsolutePath; - Method = verb.ToLower(); + Method = method.ToLower(); + ClientIP = clientIP; BodyAsBytes = bodyAsBytes; Body = body; BodyEncoding = bodyEncoding; @@ -100,14 +108,16 @@ namespace WireMock (dict, term) => { var parts = term.Split('='); - var key = parts[0]; + string key = parts[0]; if (!dict.ContainsKey(key)) { dict.Add(key, new WireMockList()); } if (parts.Length == 2) + { dict[key].Add(parts[1]); + } return dict; }); diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index c939bc1c..a06e8da8 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -18,6 +18,7 @@ namespace WireMock.Serialization var request = (Request)mapping.RequestMatcher; var response = (Response)mapping.Provider; + var clientIPMatchers = request.GetRequestMessageMatchers(); var pathMatchers = request.GetRequestMessageMatchers(); var urlMatchers = request.GetRequestMessageMatchers(); var headerMatchers = request.GetRequestMessageMatchers(); @@ -33,6 +34,12 @@ namespace WireMock.Serialization Priority = mapping.Priority, Request = new RequestModel { + ClientIP = clientIPMatchers != null && clientIPMatchers.Any() ? new ClientIPModel + { + Matchers = Map(clientIPMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), + Funcs = Map(clientIPMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs)) + } : null, + Path = pathMatchers != null && pathMatchers.Any() ? new PathModel { Matchers = Map(pathMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)), @@ -184,6 +191,5 @@ namespace WireMock.Serialization throw new NotSupportedException($"Matcher '{matcherName}' is not supported."); } } - } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index ad2efc3f..a76ca7d8 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -377,6 +377,7 @@ namespace WireMock.Server Request = new LogRequestModel { DateTime = logEntry.RequestMessage.DateTime, + ClientIP = logEntry.RequestMessage.ClientIP, Path = logEntry.RequestMessage.Path, AbsoluteUrl = logEntry.RequestMessage.Url, Query = logEntry.RequestMessage.Query, @@ -451,6 +452,23 @@ namespace WireMock.Server { IRequestBuilder requestBuilder = Request.Create(); + if (requestModel.ClientIP != null) + { + string clientIP = requestModel.ClientIP as string; + if (clientIP != null) + { + requestBuilder = requestBuilder.WithClientIP(clientIP); + } + else + { + var clientIPModel = JsonUtils.ParseJTokenToObject(requestModel.ClientIP); + if (clientIPModel?.Matchers != null) + { + requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MappingConverter.Map).ToArray()); + } + } + } + if (requestModel.Path != null) { string path = requestModel.Path as string; diff --git a/test/WireMock.Net.Tests/RequestMessageTests.cs b/test/WireMock.Net.Tests/RequestMessageTests.cs index aa630bf9..839abab6 100644 --- a/test/WireMock.Net.Tests/RequestMessageTests.cs +++ b/test/WireMock.Net.Tests/RequestMessageTests.cs @@ -8,11 +8,13 @@ namespace WireMock.Net.Tests //[TestFixture] public class RequestMessageTests { + private const string clientIP = "::1"; + [Fact] public void Should_handle_empty_query() { // given - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP); // then Check.That(request.GetParameter("not_there")).IsNull(); @@ -24,7 +26,7 @@ namespace WireMock.Net.Tests // given string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost?foo=bar&multi=1&multi=2"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost?foo=bar&multi=1&multi=2"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); // then Check.That(request.GetParameter("foo")).Contains("bar"); @@ -32,4 +34,4 @@ namespace WireMock.Net.Tests Check.That(request.GetParameter("multi")).Contains("2"); } } -} +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestTests.ClientIP.cs b/test/WireMock.Net.Tests/RequestTests.ClientIP.cs new file mode 100644 index 00000000..b089bdd4 --- /dev/null +++ b/test/WireMock.Net.Tests/RequestTests.ClientIP.cs @@ -0,0 +1,41 @@ + +using System; +using NFluent; +using WireMock.Matchers.Request; +using WireMock.RequestBuilders; +using Xunit; + +namespace WireMock.Net.Tests +{ + //[TestFixture] + public partial class RequestTests + { + [Fact] + public void Request_WithClientIP_Match_Ok() + { + // given + var spec = Request.Create().WithClientIP("127.0.0.2", "1.1.1.1"); + + // when + var request = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.2"); + + // then + var requestMatchResult = new RequestMatchResult(); + Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0); + } + + [Fact] + public void Request_WithClientIP_Match_Fail() + { + // given + var spec = Request.Create().WithClientIP("127.0.0.2"); + + // when + var request = new RequestMessage(new Uri("http://localhost"), "GET", "192.1.1.1"); + + // then + var requestMatchResult = new RequestMatchResult(); + Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.0); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/RequestTests.cs b/test/WireMock.Net.Tests/RequestTests.cs index 949713a3..521a7d1d 100644 --- a/test/WireMock.Net.Tests/RequestTests.cs +++ b/test/WireMock.Net.Tests/RequestTests.cs @@ -10,8 +10,10 @@ using WireMock.Matchers.Request; namespace WireMock.Net.Tests { //[TestFixture] - public class RequestTests + public partial class RequestTests { + private const string clientIP = "::1"; + [Fact] public void Should_specify_requests_matching_given_path() { @@ -19,7 +21,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo"); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -31,8 +33,8 @@ namespace WireMock.Net.Tests { var requestBuilder = Request.Create().WithPath("/x1", "/x2"); - var request1 = new RequestMessage(new Uri("http://localhost/x1"), "blabla"); - var request2 = new RequestMessage(new Uri("http://localhost/x2"), "blabla"); + var request1 = new RequestMessage(new Uri("http://localhost/x1"), "blabla", clientIP); + var request2 = new RequestMessage(new Uri("http://localhost/x2"), "blabla", clientIP); var requestMatchResult = new RequestMatchResult(); Check.That(requestBuilder.GetMatchingScore(request1, requestMatchResult)).IsEqualTo(1.0); @@ -46,7 +48,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath(url => url.EndsWith("/foo")); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -60,7 +62,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath(new RegexMatcher("^/foo")); // when - var request = new RequestMessage(new Uri("http://localhost/foo/bar"), "blabla"); + var request = new RequestMessage(new Uri("http://localhost/foo/bar"), "blabla", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -74,7 +76,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo"); // when - var request = new RequestMessage(new Uri("http://localhost/bar"), "blabla"); + var request = new RequestMessage(new Uri("http://localhost/bar"), "blabla", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -88,7 +90,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithUrl("*/foo"); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -102,7 +104,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo").UsingPut(); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -116,7 +118,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo").UsingPost(); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -130,7 +132,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo").UsingGet(); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "GET"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "GET", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -146,7 +148,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "Delete", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "Delete", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -160,7 +162,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo").UsingHead(); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -174,7 +176,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/foo").UsingPut(); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "HEAD", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -188,7 +190,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithPath("/bar").UsingPut(); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT"); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -204,7 +206,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tata" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tata" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -220,7 +222,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tata" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tata" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -236,7 +238,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "ABC" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "ABC" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -252,7 +254,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "whatever"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "TaTa" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "TaTa" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -266,7 +268,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().UsingAnyVerb().WithCookie("session", "a*"); // when - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", null, null, null, null, new Dictionary { { "session", "abc" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, null, null, null, null, new Dictionary { { "session", "abc" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -282,7 +284,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "Hello world!"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -298,7 +300,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "cat"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -314,7 +316,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "cat"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -330,7 +332,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "caR"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -346,7 +348,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "The car drives in the street."; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -362,7 +364,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "Hello"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -378,7 +380,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "Hello world!"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tatata" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tatata" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -394,7 +396,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "Hello world!"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -415,7 +417,7 @@ namespace WireMock.Net.Tests xyz "; byte[] body = Encoding.UTF8.GetBytes(xmlBodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, xmlBodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, xmlBodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -436,7 +438,7 @@ namespace WireMock.Net.Tests xyz "; byte[] body = Encoding.UTF8.GetBytes(xmlBodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, xmlBodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, xmlBodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -452,7 +454,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -468,7 +470,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "{ \"things\": { \"name\": \"Wiremock\" } }"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8); // then var requestMatchResult = new RequestMatchResult(); @@ -484,7 +486,7 @@ namespace WireMock.Net.Tests // when string bodyAsString = "xxx"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tatata" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "X-toto", "tatata" } }); // then var requestMatchResult = new RequestMatchResult(); @@ -498,7 +500,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithParam("bar", "1", "2"); // when - var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT"); + var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -512,7 +514,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithParam("bar"); // when - var request = new RequestMessage(new Uri("http://localhost/foo?bar"), "PUT"); + var request = new RequestMessage(new Uri("http://localhost/foo?bar"), "PUT", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -526,7 +528,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().UsingAnyVerb().WithParam(p => p.ContainsKey("bar")); // when - var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT"); + var request = new RequestMessage(new Uri("http://localhost/foo?bar=1&bar=2"), "PUT", clientIP); // then var requestMatchResult = new RequestMatchResult(); @@ -540,7 +542,7 @@ namespace WireMock.Net.Tests var spec = Request.Create().WithParam("bar", "1"); // when - var request = new RequestMessage(new Uri("http://localhost/test=7"), "PUT"); + var request = new RequestMessage(new Uri("http://localhost/test=7"), "PUT", clientIP); // then var requestMatchResult = new RequestMatchResult(); diff --git a/test/WireMock.Net.Tests/ResponseTests.cs b/test/WireMock.Net.Tests/ResponseTests.cs index e0c5d717..18635575 100644 --- a/test/WireMock.Net.Tests/ResponseTests.cs +++ b/test/WireMock.Net.Tests/ResponseTests.cs @@ -11,18 +11,20 @@ namespace WireMock.Net.Tests //[TestFixture] public class ResponseTests { + private const string clientIP = "::1"; + [Fact] public async Task Response_ProvideResponse_Handlebars_UrlPathVerb() { // given string bodyAsString = "abc"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); var response = Response.Create() .WithBody("test {{request.url}} {{request.path}} {{request.method}}") .WithTransformer(); - + // act var responseMessage = await response.ProvideResponseAsync(request); @@ -36,7 +38,7 @@ namespace WireMock.Net.Tests // given string bodyAsString = "abc"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo?a=1&a=2&b=5"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo?a=1&a=2&b=5"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); var response = Response.Create() .WithBody("test keya={{request.query.a}} idx={{request.query.a.[0]}} idx={{request.query.a.[1]}} keyb={{request.query.b}}") @@ -55,7 +57,7 @@ namespace WireMock.Net.Tests // given string bodyAsString = "abc"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8, new Dictionary { { "Content-Type", "text/plain" } }); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8, new Dictionary { { "Content-Type", "text/plain" } }); var response = Response.Create().WithHeader("x", "{{request.headers.Content-Type}}").WithBody("test").WithTransformer(); @@ -64,7 +66,7 @@ namespace WireMock.Net.Tests // then Check.That(responseMessage.Body).Equals("test"); - Check.That(responseMessage.Headers).Contains(new KeyValuePair("x", "text/plain")); + Check.That(responseMessage.Headers).Contains(new KeyValuePair("x", "text/plain")); } [Fact] @@ -73,7 +75,7 @@ namespace WireMock.Net.Tests // given string bodyAsString = "abc"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); var response = Response.Create().WithBody("test", Encoding.ASCII); @@ -91,7 +93,7 @@ namespace WireMock.Net.Tests // given string bodyAsString = "abc"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); - var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString, Encoding.UTF8); + var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", clientIP, body, bodyAsString, Encoding.UTF8); var response = Response.Create().WithBodyAsJson(new { value = "test" }, Encoding.ASCII); diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index 00e50fb0..5d9204a4 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -14,7 +14,7 @@ - +