diff --git a/Directory.Build.props b/Directory.Build.props index 3b2d07f13..b65ca2548 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.0.31 + 1.0.32 diff --git a/src/WireMock.Net/RequestBuilders/Request.cs b/src/WireMock.Net/RequestBuilders/Request.cs index 8864c1585..e8f5986eb 100644 --- a/src/WireMock.Net/RequestBuilders/Request.cs +++ b/src/WireMock.Net/RequestBuilders/Request.cs @@ -40,7 +40,7 @@ private Request(IList requestMatchers) : base(requestMatchers) /// A List{T} public IList GetRequestMessageMatchers() where T : IRequestMatcher { - return new ReadOnlyCollection(_requestMatchers.Where(rm => rm is T).Cast().ToList()); + return new ReadOnlyCollection(_requestMatchers.OfType().ToList()); } /// @@ -50,7 +50,7 @@ public IList GetRequestMessageMatchers() where T : IRequestMatcher /// A RequestMatcher public T GetRequestMessageMatcher() where T : IRequestMatcher { - return _requestMatchers.Where(rm => rm is T).Cast().FirstOrDefault(); + return _requestMatchers.OfType().FirstOrDefault(); } /// diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index 85ec78d21..1cbcd4353 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -1,8 +1,8 @@ -using JetBrains.Annotations; -using SimMetrics.Net; -using System; +using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; +using SimMetrics.Net; using WireMock.Admin.Mappings; using WireMock.Matchers; using WireMock.Settings; @@ -36,7 +36,7 @@ public IMatcher Map([CanBeNull] MatcherModel matcher) string matcherName = parts[0]; string matcherType = parts.Length > 1 ? parts[1] : null; - string[] stringPatterns = matcher.Patterns != null ? matcher.Patterns.Cast().ToArray() : new[] { matcher.Pattern as string }; + string[] stringPatterns = matcher.Patterns != null ? matcher.Patterns.OfType().ToArray() : new[] { matcher.Pattern as string }; MatchBehaviour matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch; switch (matcherName) @@ -48,8 +48,7 @@ public IMatcher Map([CanBeNull] MatcherModel matcher) return new ExactMatcher(matchBehaviour, stringPatterns); case "ExactObjectMatcher": - var bytePattern = Convert.FromBase64String(stringPatterns[0]); - return new ExactObjectMatcher(matchBehaviour, bytePattern); + return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0]); case "RegexMatcher": return new RegexMatcher(matchBehaviour, stringPatterns, matcher.IgnoreCase == true); @@ -64,7 +63,7 @@ public IMatcher Map([CanBeNull] MatcherModel matcher) return new JmesPathMatcher(matchBehaviour, stringPatterns); case "XPathMatcher": - return new XPathMatcher(matchBehaviour, (string)matcher.Pattern); + return new XPathMatcher(matchBehaviour, stringPatterns); case "WildcardMatcher": return new WildcardMatcher(matchBehaviour, stringPatterns, matcher.IgnoreCase == true); @@ -76,13 +75,28 @@ public IMatcher Map([CanBeNull] MatcherModel matcher) throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported."); } - return new SimMetricsMatcher(matchBehaviour, (string)matcher.Pattern, type); + return new SimMetricsMatcher(matchBehaviour, stringPatterns, type); default: throw new NotSupportedException($"Matcher '{matcherName}' is not supported."); } } + private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, string stringPattern) + { + byte[] bytePattern; + try + { + bytePattern = Convert.FromBase64String(stringPattern); + } + catch + { + throw new ArgumentException($"Matcher 'ExactObjectMatcher' has invalid pattern. The pattern value '{stringPattern}' is not a Base64String.", nameof(stringPattern)); + } + + return new ExactObjectMatcher(matchBehaviour, bytePattern); + } + public MatcherModel[] Map([CanBeNull] IEnumerable matchers) { return matchers?.Select(Map).Where(m => m != null).ToArray(); diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index 946c6f0c0..9cc2a399f 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -653,7 +653,7 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathO var clientIPModel = JsonUtils.ParseJTokenToObject(requestModel.ClientIP); if (clientIPModel?.Matchers != null) { - requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(_matcherMapper.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(_matcherMapper.Map).OfType().ToArray()); } } } @@ -671,7 +671,7 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathO var pathModel = JsonUtils.ParseJTokenToObject(requestModel.Path); if (pathModel?.Matchers != null) { - requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(_matcherMapper.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(_matcherMapper.Map).OfType().ToArray()); pathOrUrlmatchersValid = true; } } @@ -688,7 +688,7 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathO var urlModel = JsonUtils.ParseJTokenToObject(requestModel.Url); if (urlModel?.Matchers != null) { - requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(_matcherMapper.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(_matcherMapper.Map).OfType().ToArray()); pathOrUrlmatchersValid = true; } } @@ -709,7 +709,7 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathO { foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null)) { - requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(_matcherMapper.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(_matcherMapper.Map).OfType().ToArray()); } } @@ -717,7 +717,7 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathO { foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null)) { - requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(_matcherMapper.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(_matcherMapper.Map).OfType().ToArray()); } } @@ -726,7 +726,7 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathO foreach (var paramModel in requestModel.Params.Where(c => c.Matchers != null)) { bool ignoreCase = paramModel?.IgnoreCase ?? false; - requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers.Select(_matcherMapper.Map).Cast().ToArray()); + requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers.Select(_matcherMapper.Map).OfType().ToArray()); } } diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index bda8c7c5a..d4dda286f 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -57,6 +57,8 @@ internal static class BodyParser new WildcardMatcher("application/x-www-form-urlencoded", true) }; + private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None }; + public static bool ShouldParseBody([CanBeNull] string method) { if (string.IsNullOrEmpty(method)) @@ -135,12 +137,12 @@ public static async Task Parse([NotNull] Stream stream, [CanBeNull] st data.Encoding = DefaultEncoding; data.DetectedBodyType = BodyType.String; - // If string is not null or empty, try to get as Json + // If string is not null or empty, try to deserialize the string to a JObject if (!string.IsNullOrEmpty(data.BodyAsString)) { try { - data.BodyAsJson = JsonConvert.DeserializeObject(data.BodyAsString, new JsonSerializerSettings { Formatting = Formatting.Indented }); + data.BodyAsJson = JsonConvert.DeserializeObject(data.BodyAsString, JsonSerializerSettings); data.DetectedBodyType = BodyType.Json; } catch diff --git a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs index 2719eb382..e98878ce3 100644 --- a/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs +++ b/test/WireMock.Net.Tests/Serialization/MatcherModelMapperTests.cs @@ -1,6 +1,6 @@ -using NFluent; -using System; +using System; using Moq; +using NFluent; using WireMock.Admin.Mappings; using WireMock.Matchers; using WireMock.Serialization; @@ -68,7 +68,7 @@ public void MatcherModelMapper_Map_ExactMatcher_Patterns() } [Fact] - public void MatcherModelMapper_Map_ExactObjectMatcher_Pattern() + public void MatcherModelMapper_Map_ExactObjectMatcher_ValidBase64StringPattern() { // Assign var model = new MatcherModel @@ -84,6 +84,20 @@ public void MatcherModelMapper_Map_ExactObjectMatcher_Pattern() Check.That(matcher.ValueAsBytes).ContainsExactly(new byte[] { 115, 116, 101, 102 }); } + [Fact] + public void MatcherModelMapper_Map_ExactObjectMatcher_InvalidBase64StringPattern() + { + // Assign + var model = new MatcherModel + { + Name = "ExactObjectMatcher", + Patterns = new object[] { "_" } + }; + + // Act & Assert + Check.ThatCode(() => _sut.Map(model)).Throws(); + } + [Fact] public void MatcherModelMapper_Map_RegexMatcher() {