// Copyright © WireMock.Net using System; using System.Collections.Generic; using System.Linq; using Stef.Validation; using WireMock.Types; namespace WireMock.Matchers.Request; /// /// The request header matcher. /// /// public class RequestMessageHeaderMatcher : IRequestMatcher { private const string _name = nameof(RequestMessageCookieMatcher); /// /// MatchBehaviour /// public MatchBehaviour MatchBehaviour { get; } /// /// IgnoreCase /// public bool IgnoreCase { get; } /// /// The functions /// public Func, bool>[]? Funcs { get; } /// /// The name /// public string Name { get; } /// /// The matchers. /// public IStringMatcher[]? Matchers { get; } /// /// The /// public MatchOperator MatchOperator { get; } = MatchOperator.Or; /// /// Initializes a new instance of the class. /// /// The name. /// The pattern. /// Ignore the case from the pattern. /// The match behaviour. public RequestMessageHeaderMatcher(MatchBehaviour matchBehaviour, string name, string pattern, bool ignoreCase) { Guard.NotNull(name); Guard.NotNull(pattern); MatchBehaviour = matchBehaviour; IgnoreCase = ignoreCase; Name = name; Matchers = new IStringMatcher[] { new WildcardMatcher(matchBehaviour, pattern, ignoreCase) }; } /// /// Initializes a new instance of the class. /// /// The match behaviour. /// The to use. /// The name. /// The patterns. /// Ignore the case from the pattern. public RequestMessageHeaderMatcher(MatchBehaviour matchBehaviour, MatchOperator matchOperator, string name, bool ignoreCase, params string[] patterns) : this(matchBehaviour, matchOperator, name, ignoreCase, patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast().ToArray()) { Guard.NotNull(patterns); } /// /// Initializes a new instance of the class. /// /// The match behaviour. /// The to use. /// The name. /// The matchers. /// Ignore the case from the pattern. public RequestMessageHeaderMatcher(MatchBehaviour matchBehaviour, MatchOperator matchOperator, string name, bool ignoreCase, params IStringMatcher[] matchers) { Guard.NotNull(name); Guard.NotNull(matchers); MatchBehaviour = matchBehaviour; MatchOperator = matchOperator; Name = name; Matchers = matchers; IgnoreCase = ignoreCase; } /// /// Initializes a new instance of the class. /// /// The funcs. public RequestMessageHeaderMatcher(params Func, bool>[] funcs) { Funcs = Guard.NotNull(funcs); Name = string.Empty; // Not used when Func, but set to a non-null valid value. } /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { var (score, exception) = GetMatchResult(requestMessage).Expand(); return requestMatchResult.AddScore(GetType(), score, exception); } private MatchResult GetMatchResult(IRequestMessage requestMessage) { if (requestMessage.Headers == null) { return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch)); } // Check if we want to use IgnoreCase to compare the Header-Name and Header-Value(s) var headers = !IgnoreCase ? requestMessage.Headers : new Dictionary>(requestMessage.Headers, StringComparer.OrdinalIgnoreCase); if (Funcs != null) { var funcResults = Funcs.Select(f => f(headers.ToDictionary(entry => entry.Key, entry => entry.Value.ToArray()))).ToArray(); return MatchResult.From(_name, MatchScores.ToScore(funcResults, MatchOperator)); } if (Matchers != null) { if (!headers.ContainsKey(Name)) { return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch)); } var results = new List(); foreach (var matcher in Matchers) { var resultsPerMatcher = headers[Name].Select(matcher.IsMatch).ToArray(); results.Add(MatchResult.From(_name, resultsPerMatcher, MatchOperator.And)); } return MatchResult.From(_name, results, MatchOperator); } return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch)); } }