Create GraphQL project (#1334)

* Create new project for GraphQL

* ...

* .

* ok?

* Update src/WireMock.Net.Shared/Extensions/AnyOfExtensions.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* --

* ...

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Stef Heyenrath
2025-08-10 19:00:22 +02:00
committed by GitHub
parent 0d510cdde8
commit 0597a73e0e
38 changed files with 266 additions and 230 deletions

View File

@@ -1,213 +0,0 @@
// Copyright © WireMock.Net
#if GRAPHQL
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using AnyOfTypes;
using GraphQL;
using GraphQL.Types;
using GraphQLParser;
using GraphQLParser.AST;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Exceptions;
using WireMock.Extensions;
using WireMock.Matchers.Models;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// GrapQLMatcher Schema Matcher
/// </summary>
/// <inheritdoc cref="IStringMatcher"/>
public class GraphQLMatcher : IStringMatcher
{
private sealed class GraphQLRequest
{
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? Query { get; set; }
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public Dictionary<string, object?>? Variables { get; set; }
}
private readonly AnyOf<string, StringPattern>[] _patterns;
private readonly ISchema _schema;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// An optional dictionary defining the custom Scalar and the type.
/// </summary>
public IDictionary<string, Type>? CustomScalars { get; }
/// <summary>
/// Initializes a new instance of the <see cref="GraphQLMatcher"/> class.
/// </summary>
/// <param name="schema">The schema.</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
public GraphQLMatcher(
AnyOf<string, StringPattern, ISchema> schema,
MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch,
MatchOperator matchOperator = MatchOperator.Or
) : this(schema, null, matchBehaviour, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GraphQLMatcher"/> class.
/// </summary>
/// <param name="schema">The schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
public GraphQLMatcher(
AnyOf<string, StringPattern, ISchema> schema,
IDictionary<string, Type>? customScalars,
MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch,
MatchOperator matchOperator = MatchOperator.Or
)
{
Guard.NotNull(schema);
CustomScalars = customScalars;
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
var patterns = new List<AnyOf<string, StringPattern>>();
switch (schema.CurrentType)
{
case AnyOfType.First:
patterns.Add(schema.First);
_schema = BuildSchema(schema);
break;
case AnyOfType.Second:
patterns.Add(schema.Second);
_schema = BuildSchema(schema.Second.Pattern);
break;
case AnyOfType.Third:
_schema = schema.Third;
break;
default:
throw new NotSupportedException();
}
_patterns = patterns.ToArray();
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
if (input != null && TryGetGraphQLRequest(input, out var graphQLRequest))
{
try
{
var executionResult = new DocumentExecuter().ExecuteAsync(eo =>
{
eo.ThrowOnUnhandledException = true;
eo.Schema = _schema;
eo.Query = graphQLRequest.Query;
if (graphQLRequest.Variables != null)
{
eo.Variables = new Inputs(graphQLRequest.Variables);
}
}).GetAwaiter().GetResult();
if (executionResult.Errors == null || executionResult.Errors.Count == 0)
{
score = MatchScores.Perfect;
}
else
{
exception = executionResult.Errors.OfType<Exception>().ToArray().ToException();
}
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(GraphQLMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return "NotImplemented";
}
private static bool TryGetGraphQLRequest(string input, [NotNullWhen(true)] out GraphQLRequest? graphQLRequest)
{
try
{
graphQLRequest = JsonConvert.DeserializeObject<GraphQLRequest>(input);
return graphQLRequest != null;
}
catch
{
graphQLRequest = default;
return false;
}
}
/// <param name="typeDefinitions">A textual description of the schema in SDL (Schema Definition Language) format.</param>
private ISchema BuildSchema(string typeDefinitions)
{
var schema = Schema.For(typeDefinitions);
// #984
var graphTypes = schema.BuiltInTypeMappings.Select(tm => tm.graphType).ToArray();
schema.RegisterTypes(graphTypes);
var doc = Parser.Parse(typeDefinitions);
var scalarTypeDefinitions = doc.Definitions
.Where(d => d.Kind == ASTNodeKind.ScalarTypeDefinition)
.OfType<GraphQLTypeDefinition>();
foreach (var scalarTypeDefinitionName in scalarTypeDefinitions.Select(s => s.Name.StringValue))
{
var customScalarGraphTypeName = $"{scalarTypeDefinitionName}GraphType";
if (graphTypes.All(t => t.Name != customScalarGraphTypeName)) // Only process when not built-in.
{
// Check if this custom Scalar is defined in the dictionary
if (CustomScalars == null || !CustomScalars.TryGetValue(scalarTypeDefinitionName, out var clrType))
{
throw new WireMockException($"The GraphQL Scalar type '{scalarTypeDefinitionName}' is not defined in the CustomScalars dictionary.");
}
// Create a this custom Scalar GraphType (extending the WireMockCustomScalarGraphType<{clrType}> class)
var customScalarGraphType = ReflectionUtils.CreateGenericType(customScalarGraphTypeName, typeof(WireMockCustomScalarGraphType<>), clrType);
schema.RegisterType(customScalarGraphType);
}
}
return schema;
}
}
#endif

View File

@@ -1,32 +0,0 @@
// Copyright © WireMock.Net
#if GRAPHQL
using System;
using GraphQL.Types;
namespace WireMock.Matchers.Models;
/// <inheritdoc />
public abstract class WireMockCustomScalarGraphType<T> : ScalarGraphType
{
/// <inheritdoc />
public override object? ParseValue(object? value)
{
switch (value)
{
case null:
return null;
case T:
return value;
}
if (value is string && typeof(T) != typeof(string))
{
throw new InvalidCastException($"Unable to convert value '{value}' of type '{typeof(string)}' to type '{typeof(T)}'.");
}
return (T)Convert.ChangeType(value, typeof(T));
}
}
#endif

View File

@@ -1,110 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using System.Linq;
using Stef.Validation;
using WireMock.Types;
namespace WireMock.Matchers.Request;
/// <summary>
/// The request body GraphQL matcher.
/// </summary>
public class RequestMessageGraphQLMatcher : IRequestMatcher
{
/// <summary>
/// The matchers.
/// </summary>
public IMatcher[]? Matchers { get; }
/// <summary>
/// The <see cref="MatchOperator"/>
/// </summary>
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="schema">The schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. [optional]</param>
public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, string schema, IDictionary<string, Type>? customScalars = null) :
this(CreateMatcherArray(matchBehaviour, schema, customScalars))
{
}
#if GRAPHQL
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="schema">The schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. [optional]</param>
public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, GraphQL.Types.ISchema schema, IDictionary<string, Type>? customScalars = null) :
this(CreateMatcherArray(matchBehaviour, new AnyOfTypes.AnyOf<string, WireMock.Models.StringPattern, GraphQL.Types.ISchema>(schema), customScalars))
{
}
#endif
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
/// </summary>
/// <param name="matchers">The matchers.</param>
public RequestMessageGraphQLMatcher(params IMatcher[] matchers)
{
Matchers = Guard.NotNull(matchers);
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
public RequestMessageGraphQLMatcher(MatchOperator matchOperator, params IMatcher[] matchers)
{
Matchers = Guard.NotNull(matchers);
MatchOperator = matchOperator;
}
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
var results = CalculateMatchResults(requestMessage);
var (score, exception) = MatchResult.From(results, MatchOperator).Expand();
return requestMatchResult.AddScore(GetType(), score, exception);
}
private static MatchResult CalculateMatchResult(IRequestMessage requestMessage, IMatcher matcher)
{
// In case the matcher is a IStringMatcher and the body is a Json or a String, use the BodyAsString to match on.
if (matcher is IStringMatcher stringMatcher && requestMessage.BodyData?.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded)
{
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
}
return default;
}
private IReadOnlyList<MatchResult> CalculateMatchResults(IRequestMessage requestMessage)
{
return Matchers == null ? new[] { new MatchResult() } : Matchers.Select(matcher => CalculateMatchResult(requestMessage, matcher)).ToArray();
}
#if GRAPHQL
private static IMatcher[] CreateMatcherArray(
MatchBehaviour matchBehaviour,
AnyOfTypes.AnyOf<string, WireMock.Models.StringPattern, GraphQL.Types.ISchema> schema,
IDictionary<string, Type>? customScalars
)
{
return new[] { new GraphQLMatcher(schema, customScalars, matchBehaviour) }.Cast<IMatcher>().ToArray();
}
#else
private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, object schema, IDictionary<string, Type>? customScalars)
{
throw new System.NotSupportedException("The GrapQLMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower.");
}
#endif
}

View File

@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using AnyOfTypes;
using Newtonsoft.Json;
using WireMock.Models.GraphQL;
namespace WireMock.Models;
@@ -22,17 +23,16 @@ public class GraphQLSchemaDetails
/// </summary>
public StringPattern? SchemaAsStringPattern { get; set; }
#if GRAPHQL
/// <summary>
/// The GraphQL schema as a <seealso cref="GraphQL.Types.ISchema"/>.
/// The GraphQL schema as a <seealso cref="ISchemaData"/>.
/// </summary>
public GraphQL.Types.ISchema? SchemaAsISchema { get; set; }
public ISchemaData? SchemaAsISchemaData { get; set; }
/// <summary>
/// The GraphQL Schema.
/// </summary>
[JsonIgnore]
public AnyOf<string, StringPattern, GraphQL.Types.ISchema>? Schema
public AnyOf<string, StringPattern, ISchemaData>? Schema
{
get
{
@@ -46,15 +46,14 @@ public class GraphQLSchemaDetails
return SchemaAsStringPattern;
}
if (SchemaAsISchema != null)
if (SchemaAsISchemaData != null)
{
return new AnyOf<string, StringPattern, GraphQL.Types.ISchema>(SchemaAsISchema);
return new AnyOf<string, StringPattern, ISchemaData>(SchemaAsISchemaData);
}
return null;
}
}
#endif
/// <summary>
/// The custom Scalars to define for this schema.

View File

@@ -1,104 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using WireMock.Matchers;
using WireMock.Util;
namespace WireMock.RequestBuilders;
/// <summary>
/// The BodyRequestBuilder interface.
/// </summary>
public interface IBodyRequestBuilder : IProtoBufRequestBuilder
{
/// <summary>
/// WithBody: IMatcher
/// </summary>
/// <param name="matcher">The matcher.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(IMatcher matcher);
/// <summary>
/// WithBody: IMatcher[]
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(IMatcher[] matchers, MatchOperator matchOperator = MatchOperator.Or);
/// <summary>
/// WithBody: Body as string
/// </summary>
/// <param name="body">The body.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBody: Body as byte[]
/// </summary>
/// <param name="body">The body.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(byte[] body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBody: Body as object
/// </summary>
/// <param name="body">The body.</param>
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsJson: A <see cref="JsonMatcher"/> will be used to match this object.
/// </summary>
/// <param name="body">The body.</param>
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
/// <returns>A <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBody: func (string)
/// </summary>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(Func<string?, bool> func);
/// <summary>
/// WithBody: func (byte[])
/// </summary>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(Func<byte[]?, bool> func);
/// <summary>
/// WithBody: func (json object)
/// </summary>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(Func<object?, bool> func);
/// <summary>
/// WithBody: func (BodyData object)
/// </summary>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(Func<IBodyData?, bool> func);
/// <summary>
/// WithBody: Body as form-urlencoded values.
/// </summary>
/// <param name="func">The form-urlencoded values.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(Func<IDictionary<string, string>?, bool> func);
/// <summary>
/// WithBodyAsGraphQLSchema: Body as GraphQL schema as a string.
/// </summary>
/// <param name="body">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsGraphQLSchema(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
}

View File

@@ -1,49 +0,0 @@
// Copyright © WireMock.Net
using System;
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// The IClientIPRequestBuilder interface.
/// </summary>
public interface IClientIPRequestBuilder : IUrlAndPathRequestBuilder
{
/// <summary>
/// WithClientIP: add clientIP matching based on IStringMatchers.
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithClientIP(params IStringMatcher[] matchers);
/// <summary>
/// WithClientIP: add clientIP matching based on MatchOperator and IStringMatchers.
/// </summary>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithClientIP(MatchOperator matchOperator, params IStringMatcher[] matchers);
/// <summary>
/// WithClientIP: add clientIP matching based on clientIPs.
/// </summary>
/// <param name="clientIPs">The clientIPs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithClientIP(params string[] clientIPs);
/// <summary>
/// WithClientIP: add clientIP matching based on clientIPs , matchBehaviour and MatchOperator.
/// </summary>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="clientIPs">The clientIPs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] clientIPs);
/// <summary>
/// WithClientIP: add clientIP matching based on functions.
/// </summary>
/// <param name="funcs">The clientIP funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithClientIP(params Func<string, bool>[] funcs);
}

View File

@@ -1,85 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// The CookieRequestBuilder interface.
/// </summary>
public interface ICookiesRequestBuilder : IParamsRequestBuilder
{
/// <summary>
/// WithCookie: matching based on name, pattern and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour);
/// <summary>
/// WithCookie: matching based on name, pattern, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithCookie: matching based on name, patterns and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour);
/// <summary>
/// WithCookie: matching based on name, patterns, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithCookie: matching based on name and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on name, ignoreCase and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the cookie-keys.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on name, ignoreCase, matchBehaviour and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the cookie-keys.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on functions.
/// </summary>
/// <param name="funcs">The cookies funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie(params Func<IDictionary<string, string>, bool>[] funcs);
}

View File

@@ -1,83 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// The GraphQLRequestBuilder interface.
/// </summary>
public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder
{
/// <summary>
/// WithGraphQLSchema: The GraphQL schema as a string.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithGraphQLSchema(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithGraphQLSchema: The GraphQL schema as a string.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithGraphQLSchema(string schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a string.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsGraphQL(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a string.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsGraphQL(string schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
#if GRAPHQL
/// <summary>
/// WithGraphQLSchema: The GraphQL schema as a ISchema.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithGraphQLSchema: The GraphQL schema as a ISchema.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a ISchema.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsGraphQL: The GraphQL schema as a ISchema.
/// </summary>
/// <param name="schema">The GraphQL schema.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. (optional)</param>
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
#endif
}

View File

@@ -1,88 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// The HeadersRequestBuilder interface.
/// </summary>
public interface IHeadersRequestBuilder : ICookiesRequestBuilder
{
/// <summary>
/// WithHeader: matching based on name, pattern and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, string pattern, MatchBehaviour matchBehaviour);
/// <summary>
/// WithHeader: matching based on name, pattern, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithHeader: matching based on name, patterns and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, string[] patterns, MatchBehaviour matchBehaviour, MatchOperator matchOperator = MatchOperator.Or);
/// <summary>
/// WithHeader: matching based on name, patterns, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or);
/// <summary>
/// WithHeader: matching based on name and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, params IStringMatcher[] matchers);
/// <summary>
/// WithHeader: matching based on name, ignoreCase and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the header-keys.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, bool ignoreCase, params IStringMatcher[] matchers);
/// <summary>
/// WithHeader: matching based on name, ignoreCase, matchBehaviour and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the header-keys.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(string name, bool ignoreCase, MatchBehaviour matchBehaviour, MatchOperator matchOperator = MatchOperator.Or, params IStringMatcher[] matchers);
/// <summary>
/// WithHeader: matching based on functions.
/// </summary>
/// <param name="funcs">The headers funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader(params Func<IDictionary<string, string[]>, bool>[] funcs);
}

View File

@@ -1,20 +0,0 @@
// Copyright © WireMock.Net
using WireMock.Matchers;
using WireMock.Matchers.Request;
namespace WireMock.RequestBuilders;
/// <summary>
/// The HttpVersionBuilder interface.
/// </summary>
public interface IHttpVersionBuilder : IRequestMatcher
{
/// <summary>
/// WithHttpVersion
/// </summary>
/// <param name="version">The HTTP Version to match.</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHttpVersion(string version, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
}

View File

@@ -1,96 +0,0 @@
// Copyright © WireMock.Net
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// The MethodRequestBuilder interface.
/// </summary>
public interface IMethodRequestBuilder : IHeadersRequestBuilder
{
/// <summary>
/// UsingConnect: add HTTP Method matching on `CONNECT` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingConnect(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingDelete: add HTTP Method matching on `DELETE` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingDelete(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingGet: add HTTP Method matching on `GET` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingGet(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingHead: Add HTTP Method matching on `HEAD` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingHead(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingPost: add HTTP Method matching on `POST` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingPost(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingPatch: add HTTP Method matching on `PATCH` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingPatch(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingPut: add HTTP Method matching on `OPTIONS` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingOptions(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingPut: add HTTP Method matching on `PUT` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingPut(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingTrace: add HTTP Method matching on `TRACE` and matchBehaviour (optional).
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingTrace(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// UsingAnyMethod: add HTTP Method matching on any method.
/// </summary>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingAnyMethod();
/// <summary>
/// UsingMethod: add HTTP Method matching on any methods and matchBehaviour.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="methods">The method or methods.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingMethod(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params string[] methods);
/// <summary>
/// UsingMethod: add HTTP Method matching on any methods.
/// </summary>
/// <param name="methods">The method or methods.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder UsingMethod(params string[] methods);
}

View File

@@ -1,36 +0,0 @@
// Copyright © WireMock.Net
using WireMock.Matchers;
using WireMock.Matchers.Request;
namespace WireMock.RequestBuilders;
/// <summary>
/// The MultiPartRequestBuilder interface.
/// </summary>
public interface IMultiPartRequestBuilder : IHttpVersionBuilder
{
/// <summary>
/// WithMultiPart: IMatcher
/// </summary>
/// <param name="matcher">The matcher.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithMultiPart(IMatcher matcher);
/// <summary>
/// WithMultiPart: IMatcher[], MatchBehaviour and MatchOperator
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <param name="matchBehaviour">The <see cref="MatchBehaviour"/> to use.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or);
/// <summary>
/// WithMultiPart: MatchBehaviour and IMatcher[]
/// </summary>
/// <param name="matchBehaviour">The <see cref="MatchBehaviour"/> to use.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithMultiPart(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, params IMatcher[] matchers);
}

View File

@@ -1,110 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using WireMock.Matchers;
using WireMock.Types;
namespace WireMock.RequestBuilders;
/// <summary>
/// The ParamsRequestBuilder interface.
/// </summary>
public interface IParamsRequestBuilder : IBodyRequestBuilder
{
/// <summary>
/// WithParam: matching on key only.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="matchBehaviour">The match behaviour (optional).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithParam: matching on key only.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="matchBehaviour">The match behaviour (optional).</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithParam: matching on key and values.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="values">The values.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, params string[] values);
/// <summary>
/// WithParam: matching on key and values.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="values">The values.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values);
/// <summary>
/// WithParam: matching on key and matchers.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, params IStringMatcher[] matchers);
/// <summary>
/// WithParam: matching on key and matchers.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers);
/// <summary>
/// WithParam: matching on key, values and matchBehaviour.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="values">The values.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values);
/// <summary>
/// WithParam: matching on key, values and matchBehaviour.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="values">The values.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values);
/// <summary>
/// WithParam: matching on key, matchers and matchBehaviour.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="matchers">The matchers.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers);
/// <summary>
/// WithParam: matching on key, matchers and matchBehaviour.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="matchers">The matchers.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params IStringMatcher[] matchers);
/// <summary>
/// WithParam: matching on functions.
/// </summary>
/// <param name="funcs">The funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs);
}

View File

@@ -1,67 +0,0 @@
// Copyright © WireMock.Net
using System.Collections.Generic;
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// The ProtoBufRequestBuilder interface.
/// </summary>
public interface IProtoBufRequestBuilder : IGraphQLRequestBuilder
{
/// <summary>
/// WithBodyAsProtoBuf
/// </summary>
/// <param name="protoDefinition">The proto definition as text.</param>
/// <param name="messageType">The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}".</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsProtoBuf(string protoDefinition, string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsProtoBuf
/// </summary>
/// <param name="protoDefinition">The proto definition as text.</param>
/// <param name="messageType">The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}".</param>
/// <param name="matcher">The matcher to use to match the ProtoBuf as (json) object.</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsProtoBuf(string protoDefinition, string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsProtoBuf
/// </summary>
/// <param name="protoDefinitions">The proto definitions as text.</param>
/// <param name="messageType">The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}".</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsProtoBuf(IReadOnlyList<string> protoDefinitions, string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsProtoBuf
/// </summary>
/// <param name="protoDefinitions">The proto definitions as text.</param>
/// <param name="messageType">The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}".</param>
/// <param name="matcher">The matcher to use to match the ProtoBuf as (json) object.</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsProtoBuf(IReadOnlyList<string> protoDefinitions, string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsProtoBuf
/// </summary>
/// <param name="messageType">The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}".</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsProtoBuf(string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsProtoBuf
/// </summary>
/// <param name="messageType">The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}".</param>
/// <param name="matcher">The matcher to use to match the ProtoBuf as (json) object.</param>
/// <param name="matchBehaviour">The match behaviour. (default = "AcceptOnMatch")</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsProtoBuf(string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
}

View File

@@ -1,10 +0,0 @@
// Copyright © WireMock.Net
namespace WireMock.RequestBuilders;
/// <summary>
/// IRequestBuilder
/// </summary>
public interface IRequestBuilder : IClientIPRequestBuilder
{
}

View File

@@ -1,86 +0,0 @@
// Copyright © WireMock.Net
using System;
using WireMock.Matchers;
namespace WireMock.RequestBuilders;
/// <summary>
/// IUrlAndPathRequestBuilder
/// </summary>
public interface IUrlAndPathRequestBuilder : IMethodRequestBuilder
{
/// <summary>
/// WithPath: add path matching based on IStringMatchers.
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithPath(params IStringMatcher[] matchers);
/// <summary>
/// WithPath: add path matching based on MatchOperator and IStringMatchers.
/// </summary>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithPath(MatchOperator matchOperator, params IStringMatcher[] matchers);
/// <summary>
/// WithPath: add path matching based on paths.
/// </summary>
/// <param name="paths">The paths.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithPath(params string[] paths);
/// <summary>
/// WithPath: add path matching based on paths , matchBehaviour and MatchOperator.
/// </summary>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="paths">The paths.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithPath(MatchOperator matchOperator, params string[] paths);
/// <summary>
/// WithPath: add path matching based on functions.
/// </summary>
/// <param name="funcs">The path funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithPath(params Func<string, bool>[] funcs);
/// <summary>
/// WithUrl: add url matching based on IStringMatcher[].
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithUrl(params IStringMatcher[] matchers);
/// <summary>
/// WithUrl: add url matching based on MatchOperator and IStringMatchers.
/// </summary>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers);
/// <summary>
/// WithUrl: add url matching based on urls.
/// </summary>
/// <param name="urls">The urls.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithUrl(params string[] urls);
/// <summary>
/// WithUrl: add url matching based on urls.
/// </summary>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
/// <param name="urls">The urls.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls);
/// <summary>
/// WithUrl: add url matching based on functions.
/// </summary>
/// <param name="funcs">The url functions.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithUrl(params Func<string, bool>[] funcs);
}

View File

@@ -98,10 +98,4 @@ public partial class Request
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
return this;
}
/// <inheritdoc />
public IRequestBuilder WithBodyAsGraphQLSchema(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return WithGraphQLSchema(body, matchBehaviour);
}
}

View File

@@ -1,61 +0,0 @@
// Copyright © WireMock.Net
using System.Collections.Generic;
using System;
using WireMock.Matchers;
using WireMock.Matchers.Request;
namespace WireMock.RequestBuilders;
public partial class Request
{
/// <inheritdoc />
public IRequestBuilder WithGraphQLSchema(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return WithBodyAsGraphQL(schema, matchBehaviour);
}
/// <inheritdoc />
public IRequestBuilder WithGraphQLSchema(string schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return WithBodyAsGraphQL(schema, customScalars, matchBehaviour);
}
/// <inheritdoc />
public IRequestBuilder WithBodyAsGraphQL(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema));
}
/// <inheritdoc />
public IRequestBuilder WithBodyAsGraphQL(string schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars));
}
#if GRAPHQL
/// <inheritdoc />
public IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return WithBodyAsGraphQL(schema, matchBehaviour);
}
/// <inheritdoc />
public IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return WithBodyAsGraphQL(schema, customScalars, matchBehaviour);
}
/// <inheritdoc />
public IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema));
}
/// <inheritdoc />
public IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, IDictionary<string, Type>? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars));
}
#endif
}

View File

@@ -73,6 +73,17 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
return _requestMatchers.OfType<T>().FirstOrDefault(func);
}
public IRequestBuilder Add<T>(T requestMatcher) where T : IRequestMatcher
{
foreach (var existing in _requestMatchers.OfType<T>().ToArray())
{
_requestMatchers.Remove(existing);
}
_requestMatchers.Add(requestMatcher);
return this;
}
internal bool TryGetProtoBufMatcher([NotNullWhen(true)] out IProtoBufMatcher? protoBufMatcher)
{
protoBufMatcher = GetRequestMessageMatcher<RequestMessageProtoBufMatcher>()?.Matcher;
@@ -85,15 +96,4 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
protoBufMatcher = bodyMatcher?.Matchers?.OfType<IProtoBufMatcher>().FirstOrDefault();
return protoBufMatcher != null;
}
private IRequestBuilder Add<T>(T requestMatcher) where T : IRequestMatcher
{
foreach (var existing in _requestMatchers.OfType<T>().ToArray())
{
_requestMatchers.Remove(existing);
}
_requestMatchers.Add(requestMatcher);
return this;
}
}

View File

@@ -13,7 +13,6 @@ using WireMock.Constants;
using WireMock.Extensions;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Types;
@@ -111,15 +110,13 @@ internal class MappingConverter(MatcherMapper mapper)
sb.AppendLine($" .WithHttpVersion({requestMessageHttpVersionMatcher.HttpVersion})");
}
#if GRAPHQL
if (requestMessageGraphQLMatcher?.Matchers != null)
{
if (requestMessageGraphQLMatcher.Matchers.OfType<GraphQLMatcher>().FirstOrDefault() is { } graphQLMatcher && graphQLMatcher.GetPatterns().Any())
if (requestMessageGraphQLMatcher.Matchers.OfType<IGraphQLMatcher>().FirstOrDefault() is { } graphQLMatcher && graphQLMatcher.GetPatterns().Any())
{
sb.AppendLine($" .WithGraphQLSchema({GetString(graphQLMatcher)})");
}
}
#endif
if (requestMessageMultiPartMatcher?.Matchers != null)
{

View File

@@ -10,6 +10,7 @@ using WireMock.Admin.Mappings;
using WireMock.Extensions;
using WireMock.Matchers;
using WireMock.Models;
using WireMock.Models.GraphQL;
using WireMock.Settings;
using WireMock.Util;
@@ -70,10 +71,11 @@ internal class MatcherMapper
case nameof(ExactObjectMatcher):
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0]);
#if GRAPHQL
case nameof(GraphQLMatcher):
return new GraphQLMatcher(stringPatterns[0].GetPattern(), matcherModel.CustomScalars, matchBehaviour, matchOperator);
#endif
case "GraphQLMatcher":
var patternAsString = stringPatterns[0].GetPattern();
var schema = new AnyOf<string, StringPattern, ISchemaData>(patternAsString);
return TypeLoader.LoadNewInstance<IGraphQLMatcher>(schema, matcherModel.CustomScalars, matchBehaviour, matchOperator);
case "MimePartMatcher":
return CreateMimePartMatcher(matchBehaviour, matcherModel);
@@ -165,11 +167,10 @@ internal class MatcherMapper
case XPathMatcher xpathMatcher:
model.XmlNamespaceMap = xpathMatcher.XmlNamespaceMap;
break;
#if GRAPHQL
case GraphQLMatcher graphQLMatcher:
case IGraphQLMatcher graphQLMatcher:
model.CustomScalars = graphQLMatcher.CustomScalars;
break;
#endif
}
switch (matcher)
@@ -277,10 +278,10 @@ internal class MatcherMapper
private IMimePartMatcher CreateMimePartMatcher(MatchBehaviour matchBehaviour, MatcherModel matcher)
{
var contentTypeMatcher = Map(matcher?.ContentTypeMatcher) as IStringMatcher;
var contentDispositionMatcher = Map(matcher?.ContentDispositionMatcher) as IStringMatcher;
var contentTransferEncodingMatcher = Map(matcher?.ContentTransferEncodingMatcher) as IStringMatcher;
var contentMatcher = Map(matcher?.ContentMatcher);
var contentTypeMatcher = Map(matcher.ContentTypeMatcher) as IStringMatcher;
var contentDispositionMatcher = Map(matcher.ContentDispositionMatcher) as IStringMatcher;
var contentTransferEncodingMatcher = Map(matcher.ContentTransferEncodingMatcher) as IStringMatcher;
var contentMatcher = Map(matcher.ContentMatcher);
return TypeLoader.LoadNewInstance<IMimePartMatcher>(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher);
}

View File

@@ -1,50 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
namespace WireMock.Util;
internal static class ReflectionUtils
{
private const string DynamicModuleName = "WireMockDynamicModule";
private static readonly AssemblyName AssemblyName = new("WireMockDynamicAssembly");
private const TypeAttributes ClassAttributes =
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout;
private static readonly ConcurrentDictionary<string, Type> TypeCache = new();
public static Type CreateType(string typeName, Type? parentType = null)
{
return TypeCache.GetOrAdd(typeName, key =>
{
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(AssemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(DynamicModuleName);
var typeBuilder = moduleBuilder.DefineType(key, ClassAttributes, parentType);
// Create the type and cache it
return typeBuilder.CreateTypeInfo()!.AsType();
});
}
public static Type CreateGenericType(string typeName, Type genericTypeDefinition, params Type[] typeArguments)
{
var genericKey = $"{typeName}_{genericTypeDefinition.Name}_{string.Join(", ", typeArguments.Select(t => t.Name))}";
return TypeCache.GetOrAdd(genericKey, _ =>
{
var genericType = genericTypeDefinition.MakeGenericType(typeArguments);
// Create the type based on the genericType and cache it
return CreateType(typeName, genericType);
});
}
}

View File

@@ -1,131 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using Stef.Validation;
namespace WireMock.Util;
internal static class TypeLoader
{
private static readonly ConcurrentDictionary<string, Type> Assemblies = new();
private static readonly ConcurrentDictionary<Type, object> Instances = new();
public static TInterface LoadNewInstance<TInterface>(params object?[] args) where TInterface : class
{
var pluginType = GetPluginType<TInterface>();
return (TInterface)Activator.CreateInstance(pluginType, args)!;
}
public static TInterface LoadStaticInstance<TInterface>(params object?[] args) where TInterface : class
{
var pluginType = GetPluginType<TInterface>();
return (TInterface)Instances.GetOrAdd(pluginType, key => Activator.CreateInstance(key, args)!);
}
public static TInterface LoadNewInstanceByFullName<TInterface>(string implementationTypeFullName, params object?[] args) where TInterface : class
{
Guard.NotNullOrEmpty(implementationTypeFullName);
var pluginType = GetPluginTypeByFullName<TInterface>(implementationTypeFullName);
return (TInterface)Activator.CreateInstance(pluginType, args)!;
}
public static TInterface LoadStaticInstanceByFullName<TInterface>(string implementationTypeFullName, params object?[] args) where TInterface : class
{
Guard.NotNullOrEmpty(implementationTypeFullName);
var pluginType = GetPluginTypeByFullName<TInterface>(implementationTypeFullName);
return (TInterface)Instances.GetOrAdd(pluginType, key => Activator.CreateInstance(key, args)!);
}
private static Type GetPluginType<TInterface>() where TInterface : class
{
var key = typeof(TInterface).FullName!;
return Assemblies.GetOrAdd(key, _ =>
{
if (TryFindTypeInDlls<TInterface>(null, out var foundType))
{
return foundType;
}
throw new DllNotFoundException($"No dll found which implements interface '{key}'.");
});
}
private static Type GetPluginTypeByFullName<TInterface>(string implementationTypeFullName) where TInterface : class
{
var @interface = typeof(TInterface).FullName;
var key = $"{@interface}_{implementationTypeFullName}";
return Assemblies.GetOrAdd(key, _ =>
{
if (TryFindTypeInDlls<TInterface>(implementationTypeFullName, out var foundType))
{
return foundType;
}
throw new DllNotFoundException($"No dll found which implements Interface '{@interface}' and has FullName '{implementationTypeFullName}'.");
});
}
private static bool TryFindTypeInDlls<TInterface>(string? implementationTypeFullName, [NotNullWhen(true)] out Type? pluginType) where TInterface : class
{
#if NETSTANDARD1_3
var directoriesToSearch = new[] { AppContext.BaseDirectory };
#else
var processDirectory = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName);
var assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var directoriesToSearch = new[] { processDirectory, assemblyDirectory }
.Where(d => !string.IsNullOrEmpty(d))
.Distinct()
.ToArray();
#endif
foreach (var directory in directoriesToSearch)
{
foreach (var file in Directory.GetFiles(directory!, "*.dll"))
{
try
{
var assembly = Assembly.Load(new AssemblyName
{
Name = Path.GetFileNameWithoutExtension(file)
});
if (TryGetImplementationTypeByInterfaceAndOptionalFullName<TInterface>(assembly, implementationTypeFullName, out pluginType))
{
return true;
}
}
catch
{
// no-op: just try next .dll
}
}
}
pluginType = null;
return false;
}
private static bool TryGetImplementationTypeByInterfaceAndOptionalFullName<T>(Assembly assembly, string? implementationTypeFullName, [NotNullWhen(true)] out Type? type)
{
type = assembly
.GetTypes()
.FirstOrDefault(t =>
typeof(T).IsAssignableFrom(t) && !t.GetTypeInfo().IsInterface &&
(implementationTypeFullName == null || string.Equals(t.FullName, implementationTypeFullName, StringComparison.OrdinalIgnoreCase))
);
return type != null;
}
}

View File

@@ -126,7 +126,6 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netstandard1.3' and '$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'net452' and '$(TargetFramework)' != 'net46' and '$(TargetFramework)' != 'net461'">
<PackageReference Include="GraphQL.NewtonsoftJson" Version="8.2.1" />
<PackageReference Include="ProtoBufJsonConverter" Version="0.10.0" />
</ItemGroup>