From 3cfd489fc7719c8e137809348e9245c12bfff1ef Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Mon, 26 Feb 2024 19:20:36 +0100 Subject: [PATCH 01/20] WireMock.Net.GraphQL --- WireMock.Net Solution.sln | 7 +++ .../WireMock.Net.Console.NET8.csproj | 2 + .../Matchers/GraphQLMatcher.cs | 18 +++--- .../Models/WireMockCustomScalarGraphType.cs | 4 +- .../Request/RequestMessageGraphQLMatcher.cs | 37 +++++------- .../Properties/AssemblyInfo.cs | 6 ++ .../IRequestBuilderExtensions.cs} | 59 +++++++++++++++---- .../WireMock.Net.GraphQL.csproj | 42 +++++++++++++ src/WireMock.Net/Matchers/IGraphQLMatcher.cs | 16 +++++ .../Request/IRequestMessageGraphQLMatcher.cs | 17 ++++++ .../Models/GraphQLSchemaDetails.cs | 10 ++-- src/WireMock.Net/Properties/AssemblyInfo.cs | 1 + .../RequestBuilders/IBodyRequestBuilder.cs | 8 --- .../IProtoBufRequestBuilder.cs | 2 +- .../RequestBuilders/IRequestBuilder.cs | 3 + .../RequestBuilders/Request.WithBody.cs | 6 -- .../Request.WithGraphQLSchema.cs | 59 ------------------- src/WireMock.Net/RequestBuilders/Request.cs | 3 +- .../Serialization/MappingConverter.cs | 8 +-- .../Serialization/MatcherMapper.cs | 10 ++-- src/WireMock.Net/Util/TypeLoader.cs | 4 +- src/WireMock.Net/WireMock.Net.csproj | 4 +- .../dotnet-WireMock.csproj | 2 + .../WireMock.Net.Tests.csproj | 5 +- 24 files changed, 188 insertions(+), 145 deletions(-) rename src/{WireMock.Net => WireMock.Net.GraphQL}/Matchers/GraphQLMatcher.cs (94%) rename src/{WireMock.Net => WireMock.Net.GraphQL}/Matchers/Models/WireMockCustomScalarGraphType.cs (97%) rename src/{WireMock.Net => WireMock.Net.GraphQL}/Matchers/Request/RequestMessageGraphQLMatcher.cs (79%) create mode 100644 src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs rename src/{WireMock.Net/RequestBuilders/IGraphQLRequestBuilder.cs => WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs} (50%) create mode 100644 src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj create mode 100644 src/WireMock.Net/Matchers/IGraphQLMatcher.cs create mode 100644 src/WireMock.Net/Matchers/Request/IRequestMessageGraphQLMatcher.cs delete mode 100644 src/WireMock.Net/RequestBuilders/Request.WithGraphQLSchema.cs diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 7bc052d01..91c951776 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -114,6 +114,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueProxy", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.GrpcClient", "examples\WireMock.Net.Console.GrpcClient\WireMock.Net.Console.GrpcClient.csproj", "{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.GraphQL", "src\WireMock.Net.GraphQL\WireMock.Net.GraphQL.csproj", "{B6269AAC-170A-4346-8B9A-444DED3D9A45}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -268,6 +270,10 @@ Global {B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|Any CPU.Build.0 = Debug|Any CPU {B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|Any CPU.ActiveCfg = Release|Any CPU {B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|Any CPU.Build.0 = Release|Any CPU + {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -312,6 +318,7 @@ Global {1EA72C0F-92E9-486B-8FFE-53F992BFC4AA} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {7FC0B409-2682-40EE-B3B9-3930D6769D01} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {B1580A38-84E7-44BE-8FE7-3EE5031D74A1} = {985E0ADB-D4B4-473A-AA40-567E279B7946} + {B6269AAC-170A-4346-8B9A-444DED3D9A45} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} diff --git a/examples/WireMock.Net.Console.NET8/WireMock.Net.Console.NET8.csproj b/examples/WireMock.Net.Console.NET8/WireMock.Net.Console.NET8.csproj index ff5b2a2fa..91134a8c0 100644 --- a/examples/WireMock.Net.Console.NET8/WireMock.Net.Console.NET8.csproj +++ b/examples/WireMock.Net.Console.NET8/WireMock.Net.Console.NET8.csproj @@ -23,6 +23,8 @@ + + diff --git a/src/WireMock.Net/Matchers/GraphQLMatcher.cs b/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs similarity index 94% rename from src/WireMock.Net/Matchers/GraphQLMatcher.cs rename to src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs index fb3b1567e..b399d74ae 100644 --- a/src/WireMock.Net/Matchers/GraphQLMatcher.cs +++ b/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs @@ -1,4 +1,3 @@ -#if GRAPHQL using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -21,8 +20,8 @@ namespace WireMock.Matchers; /// /// GrapQLMatcher Schema Matcher /// -/// -public class GraphQLMatcher : IStringMatcher +/// +public class GraphQLMatcher : IGraphQLMatcher { private sealed class GraphQLRequest { @@ -40,9 +39,7 @@ private sealed class GraphQLRequest /// public MatchBehaviour MatchBehaviour { get; } - /// - /// An optional dictionary defining the custom Scalar and the type. - /// + /// public IDictionary? CustomScalars { get; } /// @@ -52,7 +49,7 @@ private sealed class GraphQLRequest /// The match behaviour. (default = "AcceptOnMatch") /// The to use. (default = "Or") public GraphQLMatcher( - AnyOf schema, + AnyOf schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or ) : this(schema, null, matchBehaviour, matchOperator) @@ -67,7 +64,7 @@ public GraphQLMatcher( /// The match behaviour. (default = "AcceptOnMatch") /// The to use. (default = "Or") public GraphQLMatcher( - AnyOf schema, + AnyOf schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or @@ -92,7 +89,7 @@ public GraphQLMatcher( break; case AnyOfType.Third: - _schema = schema.Third; + _schema = schema.Third as ISchema ?? throw new NotSupportedException(); break; default: @@ -201,5 +198,4 @@ private ISchema BuildSchema(string typeDefinitions) return schema; } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Models/WireMockCustomScalarGraphType.cs b/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs similarity index 97% rename from src/WireMock.Net/Matchers/Models/WireMockCustomScalarGraphType.cs rename to src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs index 44d8bd7fa..6389c8072 100644 --- a/src/WireMock.Net/Matchers/Models/WireMockCustomScalarGraphType.cs +++ b/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs @@ -1,4 +1,3 @@ -#if GRAPHQL using System; using GraphQL.Types; @@ -26,5 +25,4 @@ public abstract class WireMockCustomScalarGraphType : ScalarGraphType return (T)Convert.ChangeType(value, typeof(T)); } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs b/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs similarity index 79% rename from src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs rename to src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs index c8211963b..b554e05ee 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageGraphQLMatcher.cs +++ b/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs @@ -3,22 +3,19 @@ using System.Linq; using Stef.Validation; using WireMock.Types; +using WireMock.Util; namespace WireMock.Matchers.Request; /// /// The request body GraphQL matcher. /// -public class RequestMessageGraphQLMatcher : IRequestMatcher +public class RequestMessageGraphQLMatcher : IRequestMessageGraphQLMatcher { - /// - /// The matchers. - /// + /// public IMatcher[]? Matchers { get; } - /// - /// The - /// + /// public MatchOperator MatchOperator { get; } = MatchOperator.Or; /// @@ -32,7 +29,6 @@ public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, string schema { } -#if GRAPHQL /// /// Initializes a new instance of the class. /// @@ -40,10 +36,9 @@ public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, string schema /// The schema. /// A dictionary defining the custom scalars used in this schema. [optional] public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, GraphQL.Types.ISchema schema, IDictionary? customScalars = null) : - this(CreateMatcherArray(matchBehaviour, new AnyOfTypes.AnyOf(schema), customScalars)) + this(CreateMatcherArray(matchBehaviour, new AnyOfTypes.AnyOf(schema), customScalars)) { } -#endif /// /// Initializes a new instance of the class. @@ -91,19 +86,15 @@ private IReadOnlyList CalculateMatchResults(IRequestMessage request return Matchers == null ? new[] { new MatchResult() } : Matchers.Select(matcher => CalculateMatchResult(requestMessage, matcher)).ToArray(); } -#if GRAPHQL - private static IMatcher[] CreateMatcherArray( - MatchBehaviour matchBehaviour, - AnyOfTypes.AnyOf schema, - IDictionary? customScalars - ) - { - return new[] { new GraphQLMatcher(schema, customScalars, matchBehaviour) }.Cast().ToArray(); - } -#else - private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, object schema, IDictionary? customScalars) + //#if GRAPHQL + private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, AnyOfTypes.AnyOf schema, IDictionary? customScalars) { - throw new System.NotSupportedException("The GrapQLMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); + return new[] { TypeLoader.Load(schema, customScalars, matchBehaviour, MatchOperator.Or) }.Cast().ToArray(); } -#endif + //#else + // private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, object schema, IDictionary? customScalars) + // { + // throw new System.NotSupportedException("The GrapQLMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); + // } + //#endif } \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs b/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ee5b32150 --- /dev/null +++ b/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] + +// Needed for Moq in the UnitTest project +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/IGraphQLRequestBuilder.cs b/src/WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs similarity index 50% rename from src/WireMock.Net/RequestBuilders/IGraphQLRequestBuilder.cs rename to src/WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs index 7dc3cac28..e7cdaa805 100644 --- a/src/WireMock.Net/RequestBuilders/IGraphQLRequestBuilder.cs +++ b/src/WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs @@ -1,13 +1,15 @@ +// ReSharper disable InconsistentNaming using System; using System.Collections.Generic; using WireMock.Matchers; +using WireMock.Matchers.Request; namespace WireMock.RequestBuilders; /// -/// The GraphQLRequestBuilder interface. +/// IRequestBuilderExtensions extensions for GraphQL. /// -public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder +public static class IRequestBuilderExtensions { /// /// WithGraphQLSchema: The GraphQL schema as a string. @@ -15,7 +17,10 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// The GraphQL schema. /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithGraphQLSchema(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithBodyAsGraphQL(requestBuilder, schema, matchBehaviour); + } /// /// WithGraphQLSchema: The GraphQL schema as a string. @@ -24,7 +29,10 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// A dictionary defining the custom scalars used in this schema. (optional) /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithGraphQLSchema(string schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, string schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithBodyAsGraphQL(requestBuilder, schema, customScalars, matchBehaviour); + } /// /// WithBodyAsGraphQL: The GraphQL schema as a string. @@ -32,7 +40,10 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// The GraphQL schema. /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithBodyAsGraphQL(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithBodyAsGraphQL(this IRequestBuilder requestBuilder, string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return requestBuilder.Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema)); + } /// /// WithBodyAsGraphQL: The GraphQL schema as a string. @@ -41,16 +52,21 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// A dictionary defining the custom scalars used in this schema. (optional) /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithBodyAsGraphQL(string schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithBodyAsGraphQL(this IRequestBuilder requestBuilder, string schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return requestBuilder.Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars)); + } -#if GRAPHQL /// /// WithGraphQLSchema: The GraphQL schema as a ISchema. /// /// The GraphQL schema. /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithBodyAsGraphQL(requestBuilder, schema, matchBehaviour); + } /// /// WithGraphQLSchema: The GraphQL schema as a ISchema. @@ -59,7 +75,10 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// A dictionary defining the custom scalars used in this schema. (optional) /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithGraphQLSchema(this IRequestBuilder requestBuilder, GraphQL.Types.ISchema schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithBodyAsGraphQL(requestBuilder, schema, customScalars, matchBehaviour); + } /// /// WithBodyAsGraphQL: The GraphQL schema as a ISchema. @@ -67,7 +86,10 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// The GraphQL schema. /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + public static IRequestBuilder WithBodyAsGraphQL(this IRequestBuilder requestBuilder, GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return requestBuilder.Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema)); + } /// /// WithBodyAsGraphQL: The GraphQL schema as a ISchema. @@ -76,6 +98,19 @@ public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder /// A dictionary defining the custom scalars used in this schema. (optional) /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). /// The . - IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); -#endif + public static IRequestBuilder WithBodyAsGraphQL(this IRequestBuilder requestBuilder, GraphQL.Types.ISchema schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return requestBuilder.Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars)); + } + + /// + /// WithBodyAsGraphQLSchema: Body as GraphQL schema as a string. + /// + /// The GraphQL schema. + /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). + /// The . + public static IRequestBuilder WithBodyAsGraphQLSchema(this IRequestBuilder requestBuilder, string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithGraphQLSchema(requestBuilder, body, matchBehaviour); + } } \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj new file mode 100644 index 000000000..5979721f3 --- /dev/null +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -0,0 +1,42 @@ + + + + A GraphQL which can be used to match WireMock.Net Requests. + WireMock.Net.Matchers.GraphQL + Stef Heyenrath + netstandard2.0;netstandard2.1;net5.0;net6.0;net8.0 + true + wiremock;matchers;matcher;graphql + WireMock + {B6269AAC-170A-4346-8B9A-444DED3D9A45} + true + + true + true + true + ../WireMock.Net/WireMock.Net.ruleset + true + ../WireMock.Net/WireMock.Net.snk + + true + MIT + + + + true + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/IGraphQLMatcher.cs b/src/WireMock.Net/Matchers/IGraphQLMatcher.cs new file mode 100644 index 000000000..4fc5767bb --- /dev/null +++ b/src/WireMock.Net/Matchers/IGraphQLMatcher.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace WireMock.Matchers; + +/// +/// GraphQLMatcher +/// +/// +public interface IGraphQLMatcher : IStringMatcher +{ + /// + /// An optional dictionary defining the custom Scalar and the type. + /// + public IDictionary? CustomScalars { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/IRequestMessageGraphQLMatcher.cs b/src/WireMock.Net/Matchers/Request/IRequestMessageGraphQLMatcher.cs new file mode 100644 index 000000000..37d355eb7 --- /dev/null +++ b/src/WireMock.Net/Matchers/Request/IRequestMessageGraphQLMatcher.cs @@ -0,0 +1,17 @@ +namespace WireMock.Matchers.Request; + +/// +/// The request body GraphQL matcher. +/// +public interface IRequestMessageGraphQLMatcher : IRequestMatcher +{ + /// + /// The matchers. + /// + IMatcher[]? Matchers { get; } + + /// + /// The + /// + MatchOperator MatchOperator { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net/Models/GraphQLSchemaDetails.cs b/src/WireMock.Net/Models/GraphQLSchemaDetails.cs index 8188dcf93..f138102d2 100644 --- a/src/WireMock.Net/Models/GraphQLSchemaDetails.cs +++ b/src/WireMock.Net/Models/GraphQLSchemaDetails.cs @@ -20,17 +20,16 @@ public class GraphQLSchemaDetails /// public StringPattern? SchemaAsStringPattern { get; set; } -#if GRAPHQL /// - /// The GraphQL schema as a . + /// The GraphQL schema as a "GraphQL.Types.ISchema". /// - public GraphQL.Types.ISchema? SchemaAsISchema { get; set; } + public object? SchemaAsISchema { get; set; } /// /// The GraphQL Schema. /// [JsonIgnore] - public AnyOf? Schema + public AnyOf? Schema { get { @@ -46,13 +45,12 @@ public class GraphQLSchemaDetails if (SchemaAsISchema != null) { - return new AnyOf(SchemaAsISchema); + return new AnyOf(SchemaAsISchema); } return null; } } -#endif /// /// The custom Scalars to define for this schema. diff --git a/src/WireMock.Net/Properties/AssemblyInfo.cs b/src/WireMock.Net/Properties/AssemblyInfo.cs index 5aa4c57c5..a032f0efb 100644 --- a/src/WireMock.Net/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs index 49751bd45..5eb301022 100644 --- a/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs @@ -102,12 +102,4 @@ public interface IBodyRequestBuilder : IProtoBufRequestBuilder /// The form-urlencoded values. /// The . IRequestBuilder WithBody(Func?, bool> func); - - /// - /// WithBodyAsGraphQLSchema: Body as GraphQL schema as a string. - /// - /// The GraphQL schema. - /// The match behaviour. (Default is MatchBehaviour.AcceptOnMatch). - /// The . - IRequestBuilder WithBodyAsGraphQLSchema(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs index e13ec1e5d..f5db82fda 100644 --- a/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs @@ -5,7 +5,7 @@ namespace WireMock.RequestBuilders; /// /// The ProtoBufRequestBuilder interface. /// -public interface IProtoBufRequestBuilder : IGraphQLRequestBuilder +public interface IProtoBufRequestBuilder : IMultiPartRequestBuilder { /// /// WithGrpcProto diff --git a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs index 753039058..6ca5d13db 100644 --- a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs @@ -1,3 +1,5 @@ +using WireMock.Matchers.Request; + namespace WireMock.RequestBuilders; /// @@ -5,4 +7,5 @@ namespace WireMock.RequestBuilders; /// public interface IRequestBuilder : IClientIPRequestBuilder { + internal IRequestBuilder Add(T requestMatcher) where T : IRequestMatcher; } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.WithBody.cs b/src/WireMock.Net/RequestBuilders/Request.WithBody.cs index 884e4a1d6..08ffa7b32 100644 --- a/src/WireMock.Net/RequestBuilders/Request.WithBody.cs +++ b/src/WireMock.Net/RequestBuilders/Request.WithBody.cs @@ -109,10 +109,4 @@ public IRequestBuilder WithBody(Func?, bool> func) _requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func))); return this; } - - /// - public IRequestBuilder WithBodyAsGraphQLSchema(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return WithGraphQLSchema(body, matchBehaviour); - } } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.WithGraphQLSchema.cs b/src/WireMock.Net/RequestBuilders/Request.WithGraphQLSchema.cs deleted file mode 100644 index 43113c5b1..000000000 --- a/src/WireMock.Net/RequestBuilders/Request.WithGraphQLSchema.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.Generic; -using System; -using WireMock.Matchers; -using WireMock.Matchers.Request; - -namespace WireMock.RequestBuilders; - -public partial class Request -{ - /// - public IRequestBuilder WithGraphQLSchema(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return WithBodyAsGraphQL(schema, matchBehaviour); - } - - /// - public IRequestBuilder WithGraphQLSchema(string schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return WithBodyAsGraphQL(schema, customScalars, matchBehaviour); - } - - /// - public IRequestBuilder WithBodyAsGraphQL(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema)); - } - - /// - public IRequestBuilder WithBodyAsGraphQL(string schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars)); - } - -#if GRAPHQL - /// - public IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return WithBodyAsGraphQL(schema, matchBehaviour); - } - - /// - public IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return WithBodyAsGraphQL(schema, customScalars, matchBehaviour); - } - - /// - public IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema)); - } - - /// - public IRequestBuilder WithBodyAsGraphQL(GraphQL.Types.ISchema schema, IDictionary? customScalars, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema, customScalars)); - } -#endif -} \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.cs b/src/WireMock.Net/RequestBuilders/Request.cs index f375b6987..251c61d9c 100644 --- a/src/WireMock.Net/RequestBuilders/Request.cs +++ b/src/WireMock.Net/RequestBuilders/Request.cs @@ -69,7 +69,8 @@ public IList GetRequestMessageMatchers() where T : IRequestMatcher return _requestMatchers.OfType().FirstOrDefault(func); } - private IRequestBuilder Add(T requestMatcher) where T : IRequestMatcher + /// + public IRequestBuilder Add(T requestMatcher) where T : IRequestMatcher { foreach (var existing in _requestMatchers.OfType().ToArray()) { diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index a83eabf1c..da4aae564 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -48,7 +48,7 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings var methodMatcher = request.GetRequestMessageMatcher(); var requestMessageBodyMatcher = request.GetRequestMessageMatcher(); var requestMessageHttpVersionMatcher = request.GetRequestMessageMatcher(); - var requestMessageGraphQLMatcher = request.GetRequestMessageMatcher(); + var requestMessageGraphQLMatcher = request.GetRequestMessageMatcher(); var requestMessageMultiPartMatcher = request.GetRequestMessageMatcher(); var requestMessageProtoBufMatcher = request.GetRequestMessageMatcher(); @@ -114,15 +114,13 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings sb.AppendLine($" .WithHttpVersion({requestMessageHttpVersionMatcher.HttpVersion})"); } -#if GRAPHQL if (requestMessageGraphQLMatcher is { Matchers: { } }) { - if (requestMessageGraphQLMatcher.Matchers.OfType().FirstOrDefault() is { } graphQLMatcher && graphQLMatcher.GetPatterns().Any()) + if (requestMessageGraphQLMatcher.Matchers.OfType().FirstOrDefault() is { } graphQLMatcher && graphQLMatcher.GetPatterns().Any()) { sb.AppendLine($" .WithGraphQLSchema({GetString(graphQLMatcher)})"); } } -#endif #if MIMEKIT if (requestMessageMultiPartMatcher is { Matchers: { } }) @@ -259,7 +257,7 @@ public MappingModel ToMappingModel(IMapping mapping) var paramsMatchers = request.GetRequestMessageMatchers(); var methodMatcher = request.GetRequestMessageMatcher(); var bodyMatcher = request.GetRequestMessageMatcher(); - var graphQLMatcher = request.GetRequestMessageMatcher(); + var graphQLMatcher = request.GetRequestMessageMatcher(); var multiPartMatcher = request.GetRequestMessageMatcher(); var protoBufMatcher = request.GetRequestMessageMatcher(); var httpVersionMatcher = request.GetRequestMessageMatcher(); diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index 94c068d29..b7d04f229 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -65,10 +65,10 @@ public MatcherMapper(WireMockServerSettings settings) 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 schema = new AnyOf(stringPatterns[0].GetPattern()); + return TypeLoader.Load(schema, matcherModel.CustomScalars, matchBehaviour, matchOperator); #if MIMEKIT case nameof(MimePartMatcher): @@ -164,7 +164,7 @@ public MatcherMapper(WireMockServerSettings settings) model.XmlNamespaceMap = xpathMatcher.XmlNamespaceMap; break; #if GRAPHQL - case GraphQLMatcher graphQLMatcher: + case IGraphQLMatcher graphQLMatcher: model.CustomScalars = graphQLMatcher.CustomScalars; break; #endif diff --git a/src/WireMock.Net/Util/TypeLoader.cs b/src/WireMock.Net/Util/TypeLoader.cs index fcd27e779..3786a6dcb 100644 --- a/src/WireMock.Net/Util/TypeLoader.cs +++ b/src/WireMock.Net/Util/TypeLoader.cs @@ -12,7 +12,7 @@ internal static class TypeLoader { private static readonly ConcurrentDictionary Assemblies = new(); - public static TInterface Load(params object[] args) where TInterface : class + public static TInterface Load(params object?[] args) where TInterface : class { var key = typeof(TInterface).FullName!; @@ -29,7 +29,7 @@ public static TInterface Load(params object[] args) where TInterface return (TInterface)Activator.CreateInstance(pluginType, args)!; } - public static TInterface LoadByFullName(string implementationTypeFullName, params object[] args) where TInterface : class + public static TInterface LoadByFullName(string implementationTypeFullName, params object?[] args) where TInterface : class { Guard.NotNullOrEmpty(implementationTypeFullName); diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index 7da97acd3..bbbf9a64c 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -150,8 +150,8 @@ - - + diff --git a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj index 97a7089c4..8576931d3 100644 --- a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj +++ b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj @@ -21,6 +21,8 @@ + + diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index d47c90573..a41bed5bd 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -44,6 +44,10 @@ + + + + - diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index b7d04f229..7698fa728 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -163,11 +163,10 @@ public MatcherMapper(WireMockServerSettings settings) case XPathMatcher xpathMatcher: model.XmlNamespaceMap = xpathMatcher.XmlNamespaceMap; break; -#if GRAPHQL + case IGraphQLMatcher graphQLMatcher: model.CustomScalars = graphQLMatcher.CustomScalars; break; -#endif } switch (matcher) diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index bbbf9a64c..f0e59c832 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -51,7 +51,7 @@ - $(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF + $(DefineConstants);MIMEKIT;PROTOBUF From 97e5c41d9a9364e6ee4e4d776a3b27d73dd4e428 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Mon, 26 Feb 2024 21:34:15 +0100 Subject: [PATCH 03/20] WireMock.Net.MimeKitLite --- WireMock.Net Solution.sln | 7 + .../IRequestMessage.cs | 2 - .../WireMock.Net.Abstractions.csproj | 2 +- .../WireMock.Net.GraphQL.csproj | 3 +- .../Matchers/MimePartMatcher.cs | 24 +-- .../Request/RequestMessageMultiPartMatcher.cs | 21 +-- .../Properties/AssemblyInfo.cs | 6 + .../IRequestBuilderExtensions.cs | 47 ++++++ .../Util/MimeKitUtils.cs | 15 +- .../WireMock.Net.MimeKitLite.csproj | 36 +++++ src/WireMock.Net/Matchers/IGraphQLMatcher.cs | 2 +- src/WireMock.Net/Matchers/IMimePartMatcher.cs | 28 ++++ .../IRequestMessageMultiPartMatcher.cs | 17 ++ src/WireMock.Net/Properties/AssemblyInfo.cs | 1 + .../IMultiPartRequestBuilder.cs | 34 ---- .../IProtoBufRequestBuilder.cs | 2 +- .../RequestBuilders/Request.WithMultiPart.cs | 28 ---- src/WireMock.Net/RequestMessage.cs | 8 +- .../Serialization/MappingConverter.cs | 8 +- .../Serialization/MatcherMapper.cs | 22 +-- src/WireMock.Net/Util/IMimeKitUtils.cs | 8 + src/WireMock.Net/Util/TypeLoader.cs | 50 +++--- src/WireMock.Net/WireMock.Net.csproj | 5 +- .../WireMock.Net.Tests/Util/JsonUtilsTests.cs | 145 ------------------ .../WireMock.Net.Tests.csproj | 5 +- 25 files changed, 220 insertions(+), 306 deletions(-) rename src/{WireMock.Net => WireMock.Net.MimeKitLite}/Matchers/MimePartMatcher.cs (88%) rename src/{WireMock.Net => WireMock.Net.MimeKitLite}/Matchers/Request/RequestMessageMultiPartMatcher.cs (85%) create mode 100644 src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs create mode 100644 src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs rename src/{WireMock.Net => WireMock.Net.MimeKitLite}/Util/MimeKitUtils.cs (82%) create mode 100644 src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj create mode 100644 src/WireMock.Net/Matchers/IMimePartMatcher.cs create mode 100644 src/WireMock.Net/Matchers/Request/IRequestMessageMultiPartMatcher.cs delete mode 100644 src/WireMock.Net/RequestBuilders/IMultiPartRequestBuilder.cs delete mode 100644 src/WireMock.Net/RequestBuilders/Request.WithMultiPart.cs create mode 100644 src/WireMock.Net/Util/IMimeKitUtils.cs diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 91c951776..4356cc40e 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -116,6 +116,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.GrpcCl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.GraphQL", "src\WireMock.Net.GraphQL\WireMock.Net.GraphQL.csproj", "{B6269AAC-170A-4346-8B9A-444DED3D9A45}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.MimeKitLite", "src\WireMock.Net.MimeKitLite\WireMock.Net.MimeKitLite.csproj", "{F8B4A93E-46EF-4237-88FE-15FDAB7635C2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -274,6 +276,10 @@ Global {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.Build.0 = Release|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -319,6 +325,7 @@ Global {7FC0B409-2682-40EE-B3B9-3930D6769D01} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {B1580A38-84E7-44BE-8FE7-3EE5031D74A1} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {B6269AAC-170A-4346-8B9A-444DED3D9A45} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} + {F8B4A93E-46EF-4237-88FE-15FDAB7635C2} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} diff --git a/src/WireMock.Net.Abstractions/IRequestMessage.cs b/src/WireMock.Net.Abstractions/IRequestMessage.cs index 42d9c99fd..fe3e44303 100644 --- a/src/WireMock.Net.Abstractions/IRequestMessage.cs +++ b/src/WireMock.Net.Abstractions/IRequestMessage.cs @@ -116,13 +116,11 @@ public interface IRequestMessage /// byte[]? BodyAsBytes { get; } -#if MIMEKIT /// /// The original body as MimeMessage. /// Convenience getter for Handlebars and WireMockAssertions. /// object? BodyAsMimeMessage { get; } -#endif /// /// The detected body type. Convenience getter for Handlebars. diff --git a/src/WireMock.Net.Abstractions/WireMock.Net.Abstractions.csproj b/src/WireMock.Net.Abstractions/WireMock.Net.Abstractions.csproj index 9cf9ca4f6..b1c504e99 100644 --- a/src/WireMock.Net.Abstractions/WireMock.Net.Abstractions.csproj +++ b/src/WireMock.Net.Abstractions/WireMock.Net.Abstractions.csproj @@ -31,7 +31,7 @@ - $(DefineConstants);MIMEKIT;PROTOBUF + $(DefineConstants);PROTOBUF diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj index 4f6a77784..a873daef4 100644 --- a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -1,7 +1,7 @@ - A GraphQL which can be used to match WireMock.Net Requests. + GraphQL support for WireMock.Net WireMock.Net.Matchers.GraphQL Stef Heyenrath netstandard2.0;netstandard2.1;net5.0;net6.0;net8.0 @@ -10,7 +10,6 @@ WireMock {B6269AAC-170A-4346-8B9A-444DED3D9A45} true - true true true diff --git a/src/WireMock.Net/Matchers/MimePartMatcher.cs b/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs similarity index 88% rename from src/WireMock.Net/Matchers/MimePartMatcher.cs rename to src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs index 145052826..fe6a84960 100644 --- a/src/WireMock.Net/Matchers/MimePartMatcher.cs +++ b/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs @@ -1,9 +1,6 @@ -#if MIMEKIT using System; using MimeKit; -using WireMock.Matchers; using WireMock.Matchers.Helpers; -using WireMock.Models; using WireMock.Util; namespace WireMock.Matchers; @@ -11,31 +8,23 @@ namespace WireMock.Matchers; /// /// MimePartMatcher /// -public class MimePartMatcher : IMatcher +public class MimePartMatcher : IMimePartMatcher { private readonly Func[] _funcs; /// public string Name => nameof(MimePartMatcher); - /// - /// ContentType Matcher (image/png; name=image.png.) - /// + /// public IStringMatcher? ContentTypeMatcher { get; } - /// - /// ContentDisposition Matcher (attachment; filename=image.png) - /// + /// public IStringMatcher? ContentDispositionMatcher { get; } - /// - /// ContentTransferEncoding Matcher (base64) - /// + /// public IStringMatcher? ContentTransferEncodingMatcher { get; } - /// - /// Content Matcher - /// + /// public IMatcher? ContentMatcher { get; } /// @@ -116,5 +105,4 @@ private MatchResult MatchOnContent(MimePart mimePart) { return contentType?.ToString().Replace("Content-Type: ", string.Empty); } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs b/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs similarity index 85% rename from src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs rename to src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs index 4695cb71b..600ba9e23 100644 --- a/src/WireMock.Net/Matchers/Request/RequestMessageMultiPartMatcher.cs +++ b/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using MimeKit; using Stef.Validation; using WireMock.Util; @@ -9,16 +10,12 @@ namespace WireMock.Matchers.Request; /// /// The request body MultiPart matcher. /// -public class RequestMessageMultiPartMatcher : IRequestMatcher +public class RequestMessageMultiPartMatcher : IRequestMessageMultiPartMatcher { - /// - /// The matchers. - /// + /// public IMatcher[]? Matchers { get; } - /// - /// The - /// + /// public MatchOperator MatchOperator { get; } = MatchOperator.Or; /// @@ -26,6 +23,8 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher /// public MatchBehaviour MatchBehaviour { get; } + private readonly MimeKitUtils _mimeKitUtils = new(); + /// /// Initializes a new instance of the class. /// @@ -51,9 +50,6 @@ public RequestMessageMultiPartMatcher(MatchBehaviour matchBehaviour, MatchOperat /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { -#if !MIMEKIT - throw new System.NotSupportedException("The MultiPartMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); -#else var score = MatchScores.Mismatch; Exception? exception = null; @@ -62,7 +58,7 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu return requestMatchResult.AddScore(GetType(), score, null); } - if (!MimeKitUtils.TryGetMimeMessage(requestMessage, out var message)) + if (!_mimeKitUtils.TryGetMimeMessage(requestMessage, out MimeMessage? message)) { return requestMatchResult.AddScore(GetType(), score, null); } @@ -71,7 +67,7 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu { var mimePartMatchers = Matchers.OfType().ToArray(); - foreach (var mimePart in message.BodyParts.OfType()) + foreach (var mimePart in message.BodyParts.OfType()) { var matchesForMimePart = new List { default }; matchesForMimePart.AddRange(mimePartMatchers.Select(matcher => matcher.IsMatch(mimePart))); @@ -98,6 +94,5 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu } return requestMatchResult.AddScore(GetType(), score, exception); -#endif } } \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs b/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ee5b32150 --- /dev/null +++ b/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] + +// Needed for Moq in the UnitTest project +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs b/src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs new file mode 100644 index 000000000..007eb05ca --- /dev/null +++ b/src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs @@ -0,0 +1,47 @@ +// ReSharper disable InconsistentNaming +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +/// +/// IRequestBuilderExtensions extensions for MultiPart Mime using MimeKitLite. +/// +public static class IRequestBuilderExtensions +{ + /// + /// WithMultiPart: IMatcher + /// + /// The . + /// The matcher. + /// The . + public static IRequestBuilder WithMultiPart(this IRequestBuilder requestBuilder, IMatcher matcher) + { + return requestBuilder.Add(new RequestMessageMultiPartMatcher(matcher)); + } + + /// + /// WithMultiPart: IMatcher[], MatchBehaviour and MatchOperator + /// + /// The . + /// The matchers. + /// The to use. + /// The to use. + /// The . + public static IRequestBuilder WithMultiPart(this IRequestBuilder requestBuilder, IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or) + { + return requestBuilder.Add(new RequestMessageMultiPartMatcher(matchBehaviour, matchOperator, matchers)); + } + + /// + /// WithMultiPart: MatchBehaviour and IMatcher[] + /// + /// The . + /// The to use. + /// The matchers. + /// The . + public static IRequestBuilder WithMultiPart(this IRequestBuilder requestBuilder, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, params IMatcher[] matchers) + { + return requestBuilder.Add(new RequestMessageMultiPartMatcher(matchBehaviour, MatchOperator.Or, matchers)); + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Util/MimeKitUtils.cs b/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs similarity index 82% rename from src/WireMock.Net/Util/MimeKitUtils.cs rename to src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs index 9bb5126e4..ea83c7c51 100644 --- a/src/WireMock.Net/Util/MimeKitUtils.cs +++ b/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs @@ -1,4 +1,3 @@ -#if MIMEKIT using System; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -11,9 +10,16 @@ namespace WireMock.Util; -internal static class MimeKitUtils +internal class MimeKitUtils : IMimeKitUtils { - public static bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out MimeMessage? mimeMessage) + public bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out object? mimeMessage) + { + var result = TryGetMimeMessage(requestMessage, out MimeMessage? value); + mimeMessage = value; + return result; + } + + public bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out MimeMessage? mimeMessage) { Guard.NotNull(requestMessage); @@ -59,5 +65,4 @@ private static byte[] FixBytes(byte[] bytes, WireMockList contentType) return result; } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj new file mode 100644 index 000000000..45ed9147d --- /dev/null +++ b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj @@ -0,0 +1,36 @@ + + + + MultiPart Mime support for WireMock.Net + WireMock.Net.Matchers.GraphQL + Stef Heyenrath + netstandard2.0;netstandard2.1;net462;net47;net48;net6.0;net8.0 + true + wiremock;matchers;matcher;graphql + WireMock + {F8B4A93E-46EF-4237-88FE-15FDAB7635D4} + true + true + true + true + ../WireMock.Net/WireMock.Net.ruleset + true + ../WireMock.Net/WireMock.Net.snk + + true + MIT + + + + true + + + + + + + + + + + \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/IGraphQLMatcher.cs b/src/WireMock.Net/Matchers/IGraphQLMatcher.cs index 4fc5767bb..b7a824143 100644 --- a/src/WireMock.Net/Matchers/IGraphQLMatcher.cs +++ b/src/WireMock.Net/Matchers/IGraphQLMatcher.cs @@ -6,7 +6,7 @@ namespace WireMock.Matchers; /// /// GraphQLMatcher /// -/// +/// public interface IGraphQLMatcher : IStringMatcher { /// diff --git a/src/WireMock.Net/Matchers/IMimePartMatcher.cs b/src/WireMock.Net/Matchers/IMimePartMatcher.cs new file mode 100644 index 000000000..d2fda6732 --- /dev/null +++ b/src/WireMock.Net/Matchers/IMimePartMatcher.cs @@ -0,0 +1,28 @@ +namespace WireMock.Matchers; + +/// +/// MimePartMatcher +/// +/// +public interface IMimePartMatcher : IMatcher +{ + /// + /// ContentType Matcher (image/png; name=image.png.) + /// + IStringMatcher? ContentTypeMatcher { get; } + + /// + /// ContentDisposition Matcher (attachment; filename=image.png) + /// + IStringMatcher? ContentDispositionMatcher { get; } + + /// + /// ContentTransferEncoding Matcher (base64) + /// + IStringMatcher? ContentTransferEncodingMatcher { get; } + + /// + /// Content Matcher + /// + IMatcher? ContentMatcher { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/IRequestMessageMultiPartMatcher.cs b/src/WireMock.Net/Matchers/Request/IRequestMessageMultiPartMatcher.cs new file mode 100644 index 000000000..269f989f8 --- /dev/null +++ b/src/WireMock.Net/Matchers/Request/IRequestMessageMultiPartMatcher.cs @@ -0,0 +1,17 @@ +namespace WireMock.Matchers.Request; + +/// +/// The request body MultiPart matcher. +/// +public interface IRequestMessageMultiPartMatcher : IRequestMatcher +{ + /// + /// The matchers. + /// + IMatcher[]? Matchers { get; } + + /// + /// The + /// + MatchOperator MatchOperator { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net/Properties/AssemblyInfo.cs b/src/WireMock.Net/Properties/AssemblyInfo.cs index a032f0efb..84691ea2e 100644 --- a/src/WireMock.Net/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net/RequestBuilders/IMultiPartRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IMultiPartRequestBuilder.cs deleted file mode 100644 index 4db8bc175..000000000 --- a/src/WireMock.Net/RequestBuilders/IMultiPartRequestBuilder.cs +++ /dev/null @@ -1,34 +0,0 @@ -using WireMock.Matchers; -using WireMock.Matchers.Request; - -namespace WireMock.RequestBuilders; - -/// -/// The MultiPartRequestBuilder interface. -/// -public interface IMultiPartRequestBuilder : IHttpVersionBuilder -{ - /// - /// WithMultiPart: IMatcher - /// - /// The matcher. - /// The . - IRequestBuilder WithMultiPart(IMatcher matcher); - - /// - /// WithMultiPart: IMatcher[], MatchBehaviour and MatchOperator - /// - /// The matchers. - /// The to use. - /// The to use. - /// The . - IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or); - - /// - /// WithMultiPart: MatchBehaviour and IMatcher[] - /// - /// The to use. - /// The matchers. - /// The . - IRequestBuilder WithMultiPart(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, params IMatcher[] matchers); -} \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs index f5db82fda..4559ee8bb 100644 --- a/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs @@ -5,7 +5,7 @@ namespace WireMock.RequestBuilders; /// /// The ProtoBufRequestBuilder interface. /// -public interface IProtoBufRequestBuilder : IMultiPartRequestBuilder +public interface IProtoBufRequestBuilder : IHttpVersionBuilder { /// /// WithGrpcProto diff --git a/src/WireMock.Net/RequestBuilders/Request.WithMultiPart.cs b/src/WireMock.Net/RequestBuilders/Request.WithMultiPart.cs deleted file mode 100644 index 64011c307..000000000 --- a/src/WireMock.Net/RequestBuilders/Request.WithMultiPart.cs +++ /dev/null @@ -1,28 +0,0 @@ -using WireMock.Matchers; -using WireMock.Matchers.Request; - -namespace WireMock.RequestBuilders; - -public partial class Request -{ - /// - public IRequestBuilder WithMultiPart(IMatcher matcher) - { - _requestMatchers.Add(new RequestMessageMultiPartMatcher(matcher)); - return this; - } - - /// - public IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or) - { - _requestMatchers.Add(new RequestMessageMultiPartMatcher(matchBehaviour, matchOperator, matchers)); - return this; - } - - /// - public IRequestBuilder WithMultiPart(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, params IMatcher[] matchers) - { - _requestMatchers.Add(new RequestMessageMultiPartMatcher(matchBehaviour, MatchOperator.Or, matchers)); - return this; - } -} \ No newline at end of file diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs index 20b4518e9..50a86e37f 100644 --- a/src/WireMock.Net/RequestMessage.cs +++ b/src/WireMock.Net/RequestMessage.cs @@ -80,11 +80,9 @@ public class RequestMessage : IRequestMessage /// public byte[]? BodyAsBytes { get; } -#if MIMEKIT /// [Newtonsoft.Json.JsonIgnore] // Issue 1001 public object? BodyAsMimeMessage { get; } -#endif /// public string? DetectedBodyType { get; } @@ -180,19 +178,17 @@ internal RequestMessage( ClientCertificate = clientCertificate; #endif -#if MIMEKIT try { - if (MimeKitUtils.TryGetMimeMessage(this, out var mimeMessage)) + if (TypeLoader.TryFindType(out _) && TypeLoader.Load().TryGetMimeMessage(this, out var mimeMessage)) { BodyAsMimeMessage = mimeMessage; } } catch { - // Ignore exception from MimeMessage.Load + // Ignore exception from IMimeKitUtils.TryGetMimeMessage } -#endif } /// diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index da4aae564..ce80c6ed4 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -49,7 +49,7 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings var requestMessageBodyMatcher = request.GetRequestMessageMatcher(); var requestMessageHttpVersionMatcher = request.GetRequestMessageMatcher(); var requestMessageGraphQLMatcher = request.GetRequestMessageMatcher(); - var requestMessageMultiPartMatcher = request.GetRequestMessageMatcher(); + var requestMessageMultiPartMatcher = request.GetRequestMessageMatcher(); var requestMessageProtoBufMatcher = request.GetRequestMessageMatcher(); var sb = new StringBuilder(); @@ -122,15 +122,13 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings } } -#if MIMEKIT if (requestMessageMultiPartMatcher is { Matchers: { } }) { - if (requestMessageMultiPartMatcher.Matchers.OfType().Any()) + if (requestMessageMultiPartMatcher.Matchers.OfType().Any()) { sb.AppendLine(" // .WithMultiPart() is not yet supported"); } } -#endif #if PROTOBUF if (requestMessageProtoBufMatcher is { Matcher: { } }) @@ -258,7 +256,7 @@ public MappingModel ToMappingModel(IMapping mapping) var methodMatcher = request.GetRequestMessageMatcher(); var bodyMatcher = request.GetRequestMessageMatcher(); var graphQLMatcher = request.GetRequestMessageMatcher(); - var multiPartMatcher = request.GetRequestMessageMatcher(); + var multiPartMatcher = request.GetRequestMessageMatcher(); var protoBufMatcher = request.GetRequestMessageMatcher(); var httpVersionMatcher = request.GetRequestMessageMatcher(); diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index 7698fa728..d00199905 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -70,10 +70,8 @@ public MatcherMapper(WireMockServerSettings settings) var schema = new AnyOf(stringPatterns[0].GetPattern()); return TypeLoader.Load(schema, matcherModel.CustomScalars, matchBehaviour, matchOperator); -#if MIMEKIT - case nameof(MimePartMatcher): + case "MimePartMatcher": return CreateMimePartMatcher(matchBehaviour, matcherModel); -#endif #if PROTOBUF case nameof(ProtoBufMatcher): @@ -198,14 +196,12 @@ public MatcherMapper(WireMockServerSettings settings) model.Pattern = objectMatcher.Value; break; -#if MIMEKIT - case MimePartMatcher mimePartMatcher: + case IMimePartMatcher mimePartMatcher: model.ContentDispositionMatcher = Map(mimePartMatcher.ContentDispositionMatcher); model.ContentMatcher = Map(mimePartMatcher.ContentMatcher); model.ContentTransferEncodingMatcher = Map(mimePartMatcher.ContentTransferEncodingMatcher); model.ContentTypeMatcher = Map(mimePartMatcher.ContentTypeMatcher); break; -#endif #if PROTOBUF case ProtoBufMatcher protoBufMatcher: @@ -263,17 +259,15 @@ private static ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchB return new ExactObjectMatcher(matchBehaviour, bytePattern); } -#if MIMEKIT - private MimePartMatcher CreateMimePartMatcher(MatchBehaviour matchBehaviour, MatcherModel matcher) + 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 new MimePartMatcher(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher); + return TypeLoader.Load(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher); } -#endif #if PROTOBUF private ProtoBufMatcher CreateProtoBufMatcher(MatchBehaviour? matchBehaviour, string protoDefinitionOrId, MatcherModel matcher) diff --git a/src/WireMock.Net/Util/IMimeKitUtils.cs b/src/WireMock.Net/Util/IMimeKitUtils.cs new file mode 100644 index 000000000..614e542a5 --- /dev/null +++ b/src/WireMock.Net/Util/IMimeKitUtils.cs @@ -0,0 +1,8 @@ +using System.Diagnostics.CodeAnalysis; + +namespace WireMock.Util; + +internal interface IMimeKitUtils +{ + bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out object? mimeMessage); +} \ No newline at end of file diff --git a/src/WireMock.Net/Util/TypeLoader.cs b/src/WireMock.Net/Util/TypeLoader.cs index 3786a6dcb..d52262480 100644 --- a/src/WireMock.Net/Util/TypeLoader.cs +++ b/src/WireMock.Net/Util/TypeLoader.cs @@ -10,43 +10,47 @@ namespace WireMock.Util; internal static class TypeLoader { - private static readonly ConcurrentDictionary Assemblies = new(); + private static readonly ConcurrentDictionary FoundTypes = new(); - public static TInterface Load(params object?[] args) where TInterface : class + public static bool TryFindType([NotNullWhen(true)] out Type? pluginType) where TInterface : class { var key = typeof(TInterface).FullName!; - var pluginType = Assemblies.GetOrAdd(key, _ => - { - if (TryFindTypeInDlls(null, out var foundType)) - { - return foundType; - } - - throw new DllNotFoundException($"No dll found which implements Interface '{key}'."); - }); + pluginType = FoundTypes.GetOrAdd(key, _ => TryFindTypeInDlls(null, out var foundType) ? foundType : null); - return (TInterface)Activator.CreateInstance(pluginType, args)!; + return pluginType != null; } - public static TInterface LoadByFullName(string implementationTypeFullName, params object?[] args) where TInterface : class + public static bool TryFindType(string implementationTypeFullName, [NotNullWhen(true)] out Type? pluginType) where TInterface : class { - Guard.NotNullOrEmpty(implementationTypeFullName); - var @interface = typeof(TInterface).FullName; var key = $"{@interface}_{implementationTypeFullName}"; - var pluginType = Assemblies.GetOrAdd(key, _ => + pluginType = FoundTypes.GetOrAdd(key, _ => TryFindTypeInDlls(implementationTypeFullName, out var foundType) ? foundType : null); + + return pluginType != null; + } + + public static TInterface Load(params object?[] args) where TInterface : class + { + if (TryFindType(out var pluginType)) { - if (TryFindTypeInDlls(implementationTypeFullName, out var foundType)) - { - return foundType; - } + return (TInterface)Activator.CreateInstance(pluginType, args)!; + } + + throw new DllNotFoundException($"No dll found which implements Interface '{typeof(TInterface).FullName}'."); + } - throw new DllNotFoundException($"No dll found which implements Interface '{@interface}' and has FullName '{implementationTypeFullName}'."); - }); + public static TInterface LoadByFullName(string implementationTypeFullName, params object?[] args) where TInterface : class + { + Guard.NotNullOrEmpty(implementationTypeFullName); + + if (TryFindType(implementationTypeFullName, out var pluginType)) + { + return (TInterface)Activator.CreateInstance(pluginType, args)!; + } - return (TInterface)Activator.CreateInstance(pluginType, args)!; + throw new DllNotFoundException($"No dll found which implements Interface '{typeof(TInterface).FullName}' and has FullName '{implementationTypeFullName}'."); } private static bool TryFindTypeInDlls(string? implementationTypeFullName, [NotNullWhen(true)] out Type? pluginType) where TInterface : class diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index f0e59c832..01b4f14af 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -51,7 +51,7 @@ - $(DefineConstants);MIMEKIT;PROTOBUF + $(DefineConstants);PROTOBUF @@ -150,9 +150,6 @@ - - diff --git a/test/WireMock.Net.Tests/Util/JsonUtilsTests.cs b/test/WireMock.Net.Tests/Util/JsonUtilsTests.cs index 600d80d07..dc240bfc8 100644 --- a/test/WireMock.Net.Tests/Util/JsonUtilsTests.cs +++ b/test/WireMock.Net.Tests/Util/JsonUtilsTests.cs @@ -1,10 +1,5 @@ using System; -using System.Linq; -using System.Linq.Dynamic.Core; -using System.Reflection; using FluentAssertions; -using Newtonsoft.Json.Linq; -using NFluent; using WireMock.Util; using Xunit; @@ -50,144 +45,4 @@ public void JsonUtils_ParseJTokenToObject_For_Invalid_Throws() // Assert action.Should().Throw(); } - - [Fact] - public void JsonUtils_GenerateDynamicLinqStatement_JToken() - { - // Assign - JToken instance = "Test"; - - // Act - string line = JsonUtils.GenerateDynamicLinqStatement(instance); - - // Assert - var queryable = new[] { instance }.AsQueryable().Select(line); - bool result = queryable.Any("it == \"Test\""); - Check.That(result).IsTrue(); - - Check.That(line).IsEqualTo("string(it)"); - } - - [Fact] - public void JsonUtils_GenerateDynamicLinqStatement_JArray_Indexer() - { - // Assign - var instance = new JObject - { - { "Items", new JArray(new JValue(4), new JValue(8)) } - }; - - // Act - string line = JsonUtils.GenerateDynamicLinqStatement(instance); - - // Assert 1 - line.Should().Be("new ((new [] { long(Items[0]), long(Items[1])}) as Items)"); - - // Assert 2 - var queryable = new[] { instance }.AsQueryable().Select(line); - bool result = queryable.Any("Items != null"); - result.Should().BeTrue(); - } - - [Fact] - public void JsonUtils_GenerateDynamicLinqStatement_JObject2() - { - // Assign - var instance = new JObject - { - {"U", new JValue(new Uri("http://localhost:80/abc?a=5"))}, - {"N", new JValue((object?) null)}, - {"G", new JValue(Guid.NewGuid())}, - {"Flt", new JValue(10.0f)}, - {"Dbl", new JValue(Math.PI)}, - {"Check", new JValue(true)}, - { - "Child", new JObject - { - {"ChildId", new JValue(4)}, - {"ChildDateTime", new JValue(new DateTime(2018, 2, 17))}, - {"TS", new JValue(TimeSpan.FromMilliseconds(999))} - } - }, - {"I", new JValue(9)}, - {"L", new JValue(long.MaxValue)}, - {"Name", new JValue("Test")} - }; - - // Act - string line = JsonUtils.GenerateDynamicLinqStatement(instance); - - // Assert 1 - line.Should().Be("new (Uri(U) as U, null as N, Guid(G) as G, double(Flt) as Flt, double(Dbl) as Dbl, bool(Check) as Check, new (long(Child.ChildId) as ChildId, DateTime(Child.ChildDateTime) as ChildDateTime, TimeSpan(Child.TS) as TS) as Child, long(I) as I, long(L) as L, string(Name) as Name)"); - - // Assert 2 - var queryable = new[] { instance }.AsQueryable().Select(line); - bool result = queryable.Any("I > 1 && L > 1"); - result.Should().BeTrue(); - } - - [Fact] - public void JsonUtils_GenerateDynamicLinqStatement_Throws() - { - // Assign - var instance = new JObject - { - { "B", new JValue(new byte[] {48, 49}) } - }; - - // Act and Assert - Check.ThatCode(() => JsonUtils.GenerateDynamicLinqStatement(instance)).Throws(); - } - - [Fact] - public void JsonUtils_CreateTypeFromJObject() - { - // Assign - var instance = new JObject - { - {"U", new JValue(new Uri("http://localhost:80/abc?a=5"))}, - {"N", new JValue((object?) null)}, - {"G", new JValue(Guid.NewGuid())}, - {"Flt", new JValue(10.0f)}, - {"Dbl", new JValue(Math.PI)}, - {"Check", new JValue(true)}, - { - "Child", new JObject - { - {"ChildId", new JValue(4)}, - {"ChildDateTime", new JValue(new DateTime(2018, 2, 17))}, - {"ChildTimeSpan", new JValue(TimeSpan.FromMilliseconds(999))} - } - }, - {"I", new JValue(9)}, - {"L", new JValue(long.MaxValue)}, - {"S", new JValue("Test")}, - {"C", new JValue('c')} - }; - - // Act - var type = JsonUtils.CreateTypeFromJObject(instance); - - // Assert - var setProperties = type - .GetProperties(BindingFlags.Public | BindingFlags.Instance) - .Where(pi => pi.GetMethod != null).Select(pi => $"{pi.GetMethod}") - .ToArray(); - - setProperties.Should().HaveCount(11); - setProperties.Should().BeEquivalentTo(new[] - { - "System.String get_U()", - "System.Object get_N()", - "System.Guid get_G()", - "Single get_Flt()", - "Single get_Dbl()", - "Boolean get_Check()", - "Child get_Child()", - "Int64 get_I()", - "Int64 get_L()", - "System.String get_S()", - "System.String get_C()" - }); - } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index a41bed5bd..976849b38 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -34,10 +34,6 @@ $(DefineConstants);TRAILINGHEADERS - - - - @@ -46,6 +42,7 @@ + + true + MIT + + + + true + + + + + + + + + + + \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/IProtoBufMatcher.cs b/src/WireMock.Net/Matchers/IProtoBufMatcher.cs index 576ee9c15..5d21f6872 100644 --- a/src/WireMock.Net/Matchers/IProtoBufMatcher.cs +++ b/src/WireMock.Net/Matchers/IProtoBufMatcher.cs @@ -1,3 +1,6 @@ +using System; +using WireMock.Models; + namespace WireMock.Matchers; /// @@ -5,4 +8,18 @@ namespace WireMock.Matchers; /// public interface IProtoBufMatcher : IDecodeBytesMatcher, IBytesMatcher { + /// + /// The Func to define the proto definition as text or id. + /// + public Func ProtoDefinition { get; } + + /// + /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". + /// + public string MessageType { get; } + + /// + /// The Matcher to use (optional). + /// + public IObjectMatcher? Matcher { get; } } \ No newline at end of file diff --git a/src/WireMock.Net/Matchers/Request/IRequestMessageProtoBufMatcher.cs b/src/WireMock.Net/Matchers/Request/IRequestMessageProtoBufMatcher.cs new file mode 100644 index 000000000..ca4bc2915 --- /dev/null +++ b/src/WireMock.Net/Matchers/Request/IRequestMessageProtoBufMatcher.cs @@ -0,0 +1,12 @@ +namespace WireMock.Matchers.Request; + +/// +/// The request body ProtoBuf matcher. +/// +public interface IRequestMessageProtoBufMatcher : IRequestMatcher +{ + /// + /// The ProtoBufMatcher. + /// + IProtoBufMatcher? Matcher { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs index c1ceb39f4..8e179c643 100644 --- a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs +++ b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs @@ -142,11 +142,9 @@ private bool IsFault(IResponseMessage responseMessage) var jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore }); return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody); -#if PROTOBUF case BodyType.ProtoBuf: var protoDefinition = responseMessage.BodyData.ProtoDefinition?.Invoke().Text; - return await ProtoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinition, responseMessage.BodyData.ProtoBufMessageType, responseMessage.BodyData.BodyAsJson).ConfigureAwait(false); -#endif + return await TypeLoader.Load().GetProtoBufMessageWithHeaderAsync(protoDefinition, responseMessage.BodyData.ProtoBufMessageType, responseMessage.BodyData.BodyAsJson).ConfigureAwait(false); case BodyType.Bytes: return responseMessage.BodyData.BodyAsBytes; diff --git a/src/WireMock.Net/Properties/AssemblyInfo.cs b/src/WireMock.Net/Properties/AssemblyInfo.cs index 84691ea2e..aa14015b8 100644 --- a/src/WireMock.Net/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("WireMock.Net.ProtoBuf, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs index 5eb301022..e666e8e2a 100644 --- a/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IBodyRequestBuilder.cs @@ -9,7 +9,7 @@ namespace WireMock.RequestBuilders; /// /// The BodyRequestBuilder interface. /// -public interface IBodyRequestBuilder : IProtoBufRequestBuilder +public interface IBodyRequestBuilder : IHttpVersionBuilder { /// /// WithBody: IMatcher diff --git a/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs deleted file mode 100644 index 4559ee8bb..000000000 --- a/src/WireMock.Net/RequestBuilders/IProtoBufRequestBuilder.cs +++ /dev/null @@ -1,45 +0,0 @@ -using WireMock.Matchers; - -namespace WireMock.RequestBuilders; - -/// -/// The ProtoBufRequestBuilder interface. -/// -public interface IProtoBufRequestBuilder : IHttpVersionBuilder -{ - /// - /// WithGrpcProto - /// - /// The proto definition as text. - /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". - /// The match behaviour. (default = "AcceptOnMatch") - /// The . - IRequestBuilder WithBodyAsProtoBuf(string protoDefinition, string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); - - /// - /// WithGrpcProto - /// - /// The proto definition as text. - /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". - /// The matcher to use to match the ProtoBuf as (json) object. - /// The match behaviour. (default = "AcceptOnMatch") - /// The . - IRequestBuilder WithBodyAsProtoBuf(string protoDefinition, string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); - - /// - /// WithGrpcProto - /// - /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". - /// The match behaviour. (default = "AcceptOnMatch") - /// The . - IRequestBuilder WithBodyAsProtoBuf(string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); - - /// - /// WithGrpcProto - /// - /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". - /// The matcher to use to match the ProtoBuf as (json) object. - /// The match behaviour. (default = "AcceptOnMatch") - /// The . - IRequestBuilder WithBodyAsProtoBuf(string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); -} \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs index 6ca5d13db..8e0e923f5 100644 --- a/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs +++ b/src/WireMock.Net/RequestBuilders/IRequestBuilder.cs @@ -7,5 +7,10 @@ namespace WireMock.RequestBuilders; /// public interface IRequestBuilder : IClientIPRequestBuilder { + /// + /// The link back to the Mapping. + /// + internal IMapping Mapping { get; set; } + internal IRequestBuilder Add(T requestMatcher) where T : IRequestMatcher; } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.WithBodyAsProtoBuf.cs b/src/WireMock.Net/RequestBuilders/Request.WithBodyAsProtoBuf.cs deleted file mode 100644 index 2c3eb187b..000000000 --- a/src/WireMock.Net/RequestBuilders/Request.WithBodyAsProtoBuf.cs +++ /dev/null @@ -1,31 +0,0 @@ -using WireMock.Matchers; -using WireMock.Matchers.Request; - -namespace WireMock.RequestBuilders; - -public partial class Request -{ - /// - public IRequestBuilder WithBodyAsProtoBuf(string protoDefinition, string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageProtoBufMatcher(matchBehaviour, () => new (null, protoDefinition), messageType)); - } - - /// - public IRequestBuilder WithBodyAsProtoBuf(string protoDefinition, string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageProtoBufMatcher(matchBehaviour, () => new(null, protoDefinition), messageType, matcher)); - } - - /// - public IRequestBuilder WithBodyAsProtoBuf(string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageProtoBufMatcher(matchBehaviour, () => Mapping.ProtoDefinition!.Value, messageType)); - } - - /// - public IRequestBuilder WithBodyAsProtoBuf(string messageType, IObjectMatcher matcher, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) - { - return Add(new RequestMessageProtoBufMatcher(matchBehaviour, () => Mapping.ProtoDefinition!.Value, messageType, matcher)); - } -} \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.cs b/src/WireMock.Net/RequestBuilders/Request.cs index 251c61d9c..c27b6c13c 100644 --- a/src/WireMock.Net/RequestBuilders/Request.cs +++ b/src/WireMock.Net/RequestBuilders/Request.cs @@ -16,9 +16,7 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder { private readonly IList _requestMatchers; - /// - /// The link back to the Mapping. - /// + /// public IMapping Mapping { get; set; } = null!; /// diff --git a/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs b/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs index 1fd6c451e..daf7add8c 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs @@ -221,18 +221,15 @@ public IResponseBuilder WithBodyAsProtoBuf( Guard.NotNullOrWhiteSpace(messageType); Guard.NotNull(value); -#if !PROTOBUF - throw new System.NotSupportedException("The WithBodyAsProtoBuf method can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); -#else ResponseMessage.BodyDestination = null; ResponseMessage.BodyData = new BodyData { DetectedBodyType = BodyType.ProtoBuf, BodyAsJson = value, - ProtoDefinition = () => new (null, protoDefinition), + ProtoDefinition = () => new(null, protoDefinition), ProtoBufMessageType = messageType }; -#endif + return this; } @@ -247,9 +244,6 @@ public IResponseBuilder WithBodyAsProtoBuf( Guard.NotNullOrWhiteSpace(messageType); Guard.NotNull(value); -#if !PROTOBUF - throw new System.NotSupportedException("The WithBodyAsProtoBuf method can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); -#else ResponseMessage.BodyDestination = null; ResponseMessage.BodyData = new BodyData { @@ -258,7 +252,7 @@ public IResponseBuilder WithBodyAsProtoBuf( ProtoDefinition = () => Mapping.ProtoDefinition ?? throw new WireMockException("ProtoDefinition cannot be resolved. You probably forgot to call .WithProtoDefinition(...) on the mapping."), ProtoBufMessageType = messageType }; -#endif + return this; } } \ No newline at end of file diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 7932dcfde..1d13b886f 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -287,7 +287,7 @@ string RemoveFirstOccurrence(string source, string find) // Check if the body matcher is a RequestMessageProtoBufMatcher and try to to decode the byte-array to a BodyAsJson. if (mapping.RequestMatcher is Request requestMatcher && requestMessage is RequestMessage request) { - var protoBufMatcher = requestMatcher.GetRequestMessageMatcher()?.Matcher; + var protoBufMatcher = requestMatcher.GetRequestMessageMatcher()?.Matcher; if (protoBufMatcher != null) { var decoded = await protoBufMatcher.DecodeAsync(request.BodyData?.BodyAsBytes).ConfigureAwait(false); diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index ce80c6ed4..e0d4953b3 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -50,7 +50,7 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings var requestMessageHttpVersionMatcher = request.GetRequestMessageMatcher(); var requestMessageGraphQLMatcher = request.GetRequestMessageMatcher(); var requestMessageMultiPartMatcher = request.GetRequestMessageMatcher(); - var requestMessageProtoBufMatcher = request.GetRequestMessageMatcher(); + var requestMessageProtoBufMatcher = request.GetRequestMessageMatcher(); var sb = new StringBuilder(); @@ -130,12 +130,10 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings } } -#if PROTOBUF if (requestMessageProtoBufMatcher is { Matcher: { } }) { sb.AppendLine(" // .WithBodyAsProtoBuf() is not yet supported"); } -#endif if (requestMessageBodyMatcher is { Matchers: { } }) { @@ -254,11 +252,11 @@ public MappingModel ToMappingModel(IMapping mapping) var cookieMatchers = request.GetRequestMessageMatchers(); var paramsMatchers = request.GetRequestMessageMatchers(); var methodMatcher = request.GetRequestMessageMatcher(); + var httpVersionMatcher = request.GetRequestMessageMatcher(); var bodyMatcher = request.GetRequestMessageMatcher(); var graphQLMatcher = request.GetRequestMessageMatcher(); var multiPartMatcher = request.GetRequestMessageMatcher(); - var protoBufMatcher = request.GetRequestMessageMatcher(); - var httpVersionMatcher = request.GetRequestMessageMatcher(); + var protoBufMatcher = request.GetRequestMessageMatcher(); var mappingModel = new MappingModel { @@ -381,13 +379,11 @@ public MappingModel ToMappingModel(IMapping mapping) { void AfterMap(MatcherModel matcherModel) { -#if PROTOBUF // In case the ProtoDefinition is defined at the Mapping level, clear the Pattern at the Matcher level - if (bodyMatchers?.OfType().Any() == true && mappingModel.ProtoDefinition != null) + if (bodyMatchers?.OfType().Any() == true && mappingModel.ProtoDefinition != null) { matcherModel.Pattern = null; } -#endif } mappingModel.Request.Body = new BodyModel(); diff --git a/src/WireMock.Net/Serialization/MatcherMapper.cs b/src/WireMock.Net/Serialization/MatcherMapper.cs index d00199905..3efc88195 100644 --- a/src/WireMock.Net/Serialization/MatcherMapper.cs +++ b/src/WireMock.Net/Serialization/MatcherMapper.cs @@ -73,10 +73,9 @@ public MatcherMapper(WireMockServerSettings settings) case "MimePartMatcher": return CreateMimePartMatcher(matchBehaviour, matcherModel); -#if PROTOBUF - case nameof(ProtoBufMatcher): + case "ProtoBufMatcher": return CreateProtoBufMatcher(matchBehaviour, stringPatterns[0].GetPattern(), matcherModel); -#endif + case nameof(RegexMatcher): return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, useRegexExtended, matchOperator); @@ -203,13 +202,11 @@ public MatcherMapper(WireMockServerSettings settings) model.ContentTypeMatcher = Map(mimePartMatcher.ContentTypeMatcher); break; -#if PROTOBUF - case ProtoBufMatcher protoBufMatcher: + case IProtoBufMatcher protoBufMatcher: model.Pattern = protoBufMatcher.ProtoDefinition().Value; model.ProtoBufMessageType = protoBufMatcher.MessageType; model.ContentMatcher = Map(protoBufMatcher.Matcher); break; -#endif } afterMap?.Invoke(model); @@ -269,8 +266,7 @@ private IMimePartMatcher CreateMimePartMatcher(MatchBehaviour matchBehaviour, Ma return TypeLoader.Load(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher); } -#if PROTOBUF - private ProtoBufMatcher CreateProtoBufMatcher(MatchBehaviour? matchBehaviour, string protoDefinitionOrId, MatcherModel matcher) + private IProtoBufMatcher CreateProtoBufMatcher(MatchBehaviour? matchBehaviour, string protoDefinitionOrId, MatcherModel matcher) { var objectMatcher = Map(matcher.ContentMatcher) as IObjectMatcher; @@ -284,12 +280,11 @@ private ProtoBufMatcher CreateProtoBufMatcher(MatchBehaviour? matchBehaviour, st protoDefinition = new(null, protoDefinitionOrId); } - return new ProtoBufMatcher( + return TypeLoader.Load( () => protoDefinition, - matcher!.ProtoBufMessageType!, + matcher.ProtoBufMessageType!, matchBehaviour ?? MatchBehaviour.AcceptOnMatch, objectMatcher ); } -#endif } \ No newline at end of file diff --git a/src/WireMock.Net/Util/IProtoBufUtils.cs b/src/WireMock.Net/Util/IProtoBufUtils.cs new file mode 100644 index 000000000..48ffdb605 --- /dev/null +++ b/src/WireMock.Net/Util/IProtoBufUtils.cs @@ -0,0 +1,17 @@ +using System.Threading; +using System.Threading.Tasks; +using JsonConverter.Abstractions; + +namespace WireMock.Util; + +internal interface IProtoBufUtils +{ + Task GetProtoBufMessageWithHeaderAsync( + string? protoDefinition, + string? messageType, + object? value, + IJsonConverter? jsonConverter = null, + JsonConverterOptions? options = null, + CancellationToken cancellationToken = default + ); +} \ No newline at end of file diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index 01b4f14af..e80e1cfe9 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -50,10 +50,6 @@ $(DefineConstants);OPENAPIPARSER - - $(DefineConstants);PROTOBUF - - $(DefineConstants);TRAILINGHEADERS @@ -149,9 +145,9 @@ - + diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index 976849b38..18340ab3e 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -43,6 +43,7 @@ + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + \ No newline at end of file diff --git a/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj b/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj index 97440b252..99ca02939 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj +++ b/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj @@ -1,52 +1,52 @@ - - A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code. - WireMock.Net.Matchers.CSharpCode - Stef Heyenrath - net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 - true - wiremock;matchers;matcher;csharp;csharpcode - WireMock - {B6269AAC-170A-4346-8B9A-444DED3D9A44} - true - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - true - true - true - ../WireMock.Net/WireMock.Net.ruleset - true - ../WireMock.Net/WireMock.Net.snk - - true - MIT - - - - true - - - - - - - - - - - - - - - - - - - - - - - - + + A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code. + WireMock.Net.Matchers.CSharpCode + Stef Heyenrath + net451;net452;net46;net461;net462;net47;net48;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + true + wiremock;matchers;matcher;csharp;csharpcode + WireMock + {B6269AAC-170A-4346-8B9A-444DED3D9A44} + true + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + true + true + ../WireMock.Net/WireMock.Net.ruleset + true + ../WireMock.Net/WireMock.Net.snk + + true + MIT + + + + true + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj index 82e6a675d..10163956b 100644 --- a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj +++ b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj @@ -1,46 +1,62 @@ - - Lightweight StandAlone Http Mocking Server for .Net. - WireMock.Net.StandAlone - Stef Heyenrath - net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 - true - WireMock.Net.StandAlone - WireMock.Net.StandAlone - tdd;mock;http;wiremock;test;server;unittest - WireMock.Net.StandAlone - {B6269AAC-170A-43D5-8B9A-579DED3D9A95} - true - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - true - true - true - WireMock.Net.StandAlone.ruleset - true - ../WireMock.Net/WireMock.Net.snk - - true - - - - - true - - - - NETSTANDARD;USE_ASPNETCORE - - - - USE_ASPNETCORE;NET46 - - - - - - - - - - + + Lightweight StandAlone Http Mocking Server for .NET which includes GraphQL-support, ProtoBuf-support, MimePartMatcher and CSharpCodeMatcher. + WireMock.Net.StandAlone + Stef Heyenrath + net451;net452;net46;net461;net462;net47;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + true + WireMock.Net.StandAlone + WireMock.Net.StandAlone + tdd;mock;http;wiremock;test;server;unittest + WireMock.Net.StandAlone + {B6269AAC-170A-43D5-8B9A-579DED3D9A95} + true + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + true + true + WireMock.Net.StandAlone.ruleset + true + ../WireMock.Net/WireMock.Net.snk + + true + + + + + true + + + + NETSTANDARD;USE_ASPNETCORE + + + + USE_ASPNETCORE;NET46 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj index 1ebbcb929..4fa56a8e8 100644 --- a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj +++ b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj @@ -1,31 +1,31 @@ - - Exe - net8.0 - true - dotnet-wiremock - A dotnet commandline tool for WireMock.Net (A Lightweight Http Mocking Server for .NET) - tdd;mock;http;wiremock;test;server;unittest;dotnet;tool;dotnet-tool - MIT - Stef Heyenrath - + + Exe + net8.0 + true + dotnet-wiremock + A dotnet commandline tool for WireMock.Net (A Lightweight Http Mocking Server for .NET) which includes GraphQL-support, ProtoBuf-support, MimePartMatcher and CSharpCodeMatcher. + tdd;mock;http;wiremock;test;server;unittest;dotnet;tool;dotnet-tool + MIT + Stef Heyenrath + - - true - + + true + - - - - + + + + - - - - - - - + + + + + + + \ No newline at end of file From e86517cfe99d53a1a1c20b39284882792409bf36 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 2 Mar 2024 16:53:14 +0100 Subject: [PATCH 08/20] !!! --- WireMock.Net Solution.sln | 31 +-- .../Matchers/GraphQLMatcher.cs | 4 +- .../Models/WireMockCustomScalarGraphType.cs | 4 +- .../Request/RequestMessageGraphQLMatcher.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- ...cs => IGraphQLRequestBuilderExtensions.cs} | 6 +- .../WireMock.Net.GraphQL.csproj | 4 +- .../Matchers/CSharpCodeMatcher.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- .../WireMock.Net.Matchers.CSharpCode.csproj | 4 +- .../Matchers/MimePartMatcher.cs | 4 +- .../Request/RequestMessageMultiPartMatcher.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- ... => IMultiPartRequestBuilderExtensions.cs} | 6 +- .../Util/MimeKitUtils.cs | 4 +- .../WireMock.Net.MimeKitLite.csproj | 2 +- .../Properties/AssemblyInfo.cs | 7 + .../WireMock.Net.Minimal.csproj | 204 ++++++++++++++++++ .../Matchers/ProtoBufMatcher.cs | 4 +- .../Request/RequestMessageProtoBufMatcher.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- ...s => IProtoBufRequestBuilderExtensions.cs} | 8 +- .../Util/ProtoBufUtils.cs | 4 +- .../WireMock.Net.ProtoBuf.csproj | 2 +- .../WireMock.Net.StandAlone.csproj | 20 +- .../WireMock.Net.StandAlone.ruleset | 4 - src/WireMock.Net/Owin/AspNetCoreSelfHost.cs | 2 - src/WireMock.Net/Properties/AssemblyInfo.cs | 8 +- src/WireMock.Net/WireMock.Net.csproj | 64 +++++- .../dotnet-WireMock.csproj | 4 - .../WireMockAdminApiTests.GetMappingsAsync.cs | 2 +- .../WireMock.Net.Tests.csproj | 36 ++-- 32 files changed, 375 insertions(+), 103 deletions(-) rename src/WireMock.Net.GraphQL/RequestBuilders/{IRequestBuilderExtensions.cs => IGraphQLRequestBuilderExtensions.cs} (98%) rename src/WireMock.Net.MimeKitLite/RequestBuilders/{IRequestBuilderExtensions.cs => IMultiPartRequestBuilderExtensions.cs} (96%) create mode 100644 src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs create mode 100644 src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj rename src/WireMock.Net.ProtoBuf/RequestBuilders/{IRequestBuilderExtensions.cs => IProtoBufRequestBuilderExtensions.cs} (96%) delete mode 100644 src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.ruleset diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 80fa2696e..bfc0bbdbd 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -116,9 +116,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.GrpcCl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.GraphQL", "src\WireMock.Net.GraphQL\WireMock.Net.GraphQL.csproj", "{B6269AAC-170A-4346-8B9A-444DED3D9A45}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.MimeKitLite", "src\WireMock.Net.MimeKitLite\WireMock.Net.MimeKitLite.csproj", "{F8B4A93E-46EF-4237-88FE-15FDAB7635C2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.MimeKitLite", "src\WireMock.Net.MimeKitLite\WireMock.Net.MimeKitLite.csproj", "{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.ProtoBuf", "src\WireMock.Net.ProtoBuf\WireMock.Net.ProtoBuf.csproj", "{B47413CD-55D3-49A7-896A-17ADBFF72407}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.ProtoBuf", "src\WireMock.Net.ProtoBuf\WireMock.Net.ProtoBuf.csproj", "{B47413AA-55D3-49A7-896A-17ADBFF72407}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Minimal", "src\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj", "{A39C689E-B94B-4BBB-A270-B5A4C2B6D179}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -278,14 +280,18 @@ Global {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.Build.0 = Release|Any CPU - {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8B4A93E-46EF-4237-88FE-15FDAB7635C2}.Release|Any CPU.Build.0 = Release|Any CPU - {B47413CD-55D3-49A7-896A-17ADBFF72407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B47413CD-55D3-49A7-896A-17ADBFF72407}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B47413CD-55D3-49A7-896A-17ADBFF72407}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B47413CD-55D3-49A7-896A-17ADBFF72407}.Release|Any CPU.Build.0 = Release|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|Any CPU.Build.0 = Release|Any CPU + {B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|Any CPU.Build.0 = Release|Any CPU + {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -331,8 +337,9 @@ Global {7FC0B409-2682-40EE-B3B9-3930D6769D01} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {B1580A38-84E7-44BE-8FE7-3EE5031D74A1} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {B6269AAC-170A-4346-8B9A-444DED3D9A45} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} - {F8B4A93E-46EF-4237-88FE-15FDAB7635C2} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} - {B47413CD-55D3-49A7-896A-17ADBFF72407} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} + {F8B4A93E-46EF-4237-88FE-15FDAB7635D4} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} + {B47413AA-55D3-49A7-896A-17ADBFF72407} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} + {A39C689E-B94B-4BBB-A270-B5A4C2B6D179} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} diff --git a/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs b/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs index b399d74ae..2bdd28481 100644 --- a/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs +++ b/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs @@ -1,3 +1,4 @@ +#if GRAPHQL using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -198,4 +199,5 @@ private ISchema BuildSchema(string typeDefinitions) return schema; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs b/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs index 6389c8072..44d8bd7fa 100644 --- a/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs +++ b/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs @@ -1,3 +1,4 @@ +#if GRAPHQL using System; using GraphQL.Types; @@ -25,4 +26,5 @@ public abstract class WireMockCustomScalarGraphType : ScalarGraphType return (T)Convert.ChangeType(value, typeof(T)); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs b/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs index ec7877451..b4dd7154e 100644 --- a/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs +++ b/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs @@ -1,3 +1,4 @@ +#if GRAPHQL using System; using System.Collections.Generic; using System.Linq; @@ -90,4 +91,5 @@ private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, AnyO { return new[] { TypeLoader.Load(schema, customScalars, matchBehaviour, MatchOperator.Or) }.Cast().ToArray(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs b/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs index ee5b32150..a2f9571eb 100644 --- a/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net.GraphQL/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] // Needed for Moq in the UnitTest project -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file +// [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs b/src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs similarity index 98% rename from src/WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs rename to src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs index 76b6a6f29..d58932110 100644 --- a/src/WireMock.Net.GraphQL/RequestBuilders/IRequestBuilderExtensions.cs +++ b/src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs @@ -1,3 +1,4 @@ +#if GRAPHQL // ReSharper disable InconsistentNaming using System; using System.Collections.Generic; @@ -10,7 +11,7 @@ namespace WireMock.RequestBuilders; /// /// IRequestBuilderExtensions extensions for GraphQL. /// -public static class IRequestBuilderExtensions +public static class IGraphQLRequestBuilderExtensions { /// /// WithGraphQLSchema: The GraphQL schema as a string. @@ -123,4 +124,5 @@ public static IRequestBuilder WithBodyAsGraphQLSchema(this IRequestBuilder reque { return WithGraphQLSchema(requestBuilder, body, matchBehaviour); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj index a873daef4..5a52a1d79 100644 --- a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -4,7 +4,7 @@ GraphQL support for WireMock.Net WireMock.Net.Matchers.GraphQL Stef Heyenrath - netstandard2.0;netstandard2.1;net5.0;net6.0;net8.0 + netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0 true wiremock;matchers;matcher;graphql WireMock @@ -31,7 +31,7 @@ - + \ No newline at end of file diff --git a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs index 90dcd3bc7..4fa6ec044 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs +++ b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs @@ -1,3 +1,4 @@ +//#if CSHARPMATCHER using System; using System.Linq; using System.Reflection; @@ -231,4 +232,5 @@ public AnyOf[] GetPatterns() /// public string Name => nameof(CSharpCodeMatcher); -} \ No newline at end of file +} +//#endif \ No newline at end of file diff --git a/src/WireMock.Net.Matchers.CSharpCode/Properties/AssemblyInfo.cs b/src/WireMock.Net.Matchers.CSharpCode/Properties/AssemblyInfo.cs index 4f81246fa..fd930200f 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net.Matchers.CSharpCode/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] // Needed for Moq in the UnitTest project -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file +// [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj b/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj index 99ca02939..c516d0d8d 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj +++ b/src/WireMock.Net.Matchers.CSharpCode/WireMock.Net.Matchers.CSharpCode.csproj @@ -4,7 +4,7 @@ A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code. WireMock.Net.Matchers.CSharpCode Stef Heyenrath - net451;net452;net46;net461;net462;net47;net48;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + net451;net452;net46;net461;net462;net47;net48;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0 true wiremock;matchers;matcher;csharp;csharpcode WireMock @@ -34,7 +34,7 @@ - + diff --git a/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs b/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs index fe6a84960..a60331671 100644 --- a/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs +++ b/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs @@ -1,3 +1,4 @@ +#if MIMEKIT using System; using MimeKit; using WireMock.Matchers.Helpers; @@ -105,4 +106,5 @@ private MatchResult MatchOnContent(MimePart mimePart) { return contentType?.ToString().Replace("Content-Type: ", string.Empty); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs b/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs index 600ba9e23..a516afbfa 100644 --- a/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs +++ b/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs @@ -1,3 +1,4 @@ +#if MIMEKIT using System; using System.Collections.Generic; using System.Linq; @@ -95,4 +96,5 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu return requestMatchResult.AddScore(GetType(), score, exception); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs b/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs index ee5b32150..a2f9571eb 100644 --- a/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] // Needed for Moq in the UnitTest project -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file +// [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs b/src/WireMock.Net.MimeKitLite/RequestBuilders/IMultiPartRequestBuilderExtensions.cs similarity index 96% rename from src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs rename to src/WireMock.Net.MimeKitLite/RequestBuilders/IMultiPartRequestBuilderExtensions.cs index 007eb05ca..3bfc372aa 100644 --- a/src/WireMock.Net.MimeKitLite/RequestBuilders/IRequestBuilderExtensions.cs +++ b/src/WireMock.Net.MimeKitLite/RequestBuilders/IMultiPartRequestBuilderExtensions.cs @@ -1,3 +1,4 @@ +#if MIMEKIT // ReSharper disable InconsistentNaming using WireMock.Matchers; using WireMock.Matchers.Request; @@ -7,7 +8,7 @@ namespace WireMock.RequestBuilders; /// /// IRequestBuilderExtensions extensions for MultiPart Mime using MimeKitLite. /// -public static class IRequestBuilderExtensions +public static class IMultiPartRequestBuilderExtensions { /// /// WithMultiPart: IMatcher @@ -44,4 +45,5 @@ public static IRequestBuilder WithMultiPart(this IRequestBuilder requestBuilder, { return requestBuilder.Add(new RequestMessageMultiPartMatcher(matchBehaviour, MatchOperator.Or, matchers)); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs b/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs index ea83c7c51..1c5fb1181 100644 --- a/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs +++ b/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs @@ -1,3 +1,4 @@ +#if MIMEKIT using System; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -65,4 +66,5 @@ private static byte[] FixBytes(byte[] bytes, WireMockList contentType) return result; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj index 60620b981..9f6c9be9a 100644 --- a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj +++ b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj @@ -30,7 +30,7 @@ - + \ No newline at end of file diff --git a/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs b/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1d42700e7 --- /dev/null +++ b/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("WireMock.Net.ProtoBuf, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +[assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +[assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +[assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +//[assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj new file mode 100644 index 000000000..a5286e6ea --- /dev/null +++ b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj @@ -0,0 +1,204 @@ + + + Minimal version for WireMock.Net + WireMock.Net.Minimal + Stef Heyenrath + net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0 + true + WireMock.Net.Minimal + WireMock.Net.Minimal + tdd;mock;http;wiremock;test;server;unittest;minimal + WireMock + {A39C689E-B94B-4BBB-A270-B5A4C2B6D179} + true + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + + true + ../WireMock.Net/WireMock.Net.snk + + true + + + + + + + + + true + + + + WireMock.Net.ruleset + + + + $(DefineConstants);NETSTANDARD;USE_ASPNETCORE + + + + $(DefineConstants);USE_ASPNETCORE + + + + $(DefineConstants);USE_ASPNETCORE;NET46 + + + + $(DefineConstants);OPENAPIPARSER + + + + $(DefineConstants);TRAILINGHEADERS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/WireMock.Net.ProtoBuf/Matchers/ProtoBufMatcher.cs b/src/WireMock.Net.ProtoBuf/Matchers/ProtoBufMatcher.cs index 4f4e63d3c..844a52d36 100644 --- a/src/WireMock.Net.ProtoBuf/Matchers/ProtoBufMatcher.cs +++ b/src/WireMock.Net.ProtoBuf/Matchers/ProtoBufMatcher.cs @@ -1,3 +1,4 @@ +#if PROTOBUF using System; using System.Threading; using System.Threading.Tasks; @@ -103,4 +104,5 @@ public async Task IsMatchAsync(byte[]? input, CancellationToken can return null; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.ProtoBuf/Matchers/Request/RequestMessageProtoBufMatcher.cs b/src/WireMock.Net.ProtoBuf/Matchers/Request/RequestMessageProtoBufMatcher.cs index f002d5442..57db5ac0a 100644 --- a/src/WireMock.Net.ProtoBuf/Matchers/Request/RequestMessageProtoBufMatcher.cs +++ b/src/WireMock.Net.ProtoBuf/Matchers/Request/RequestMessageProtoBufMatcher.cs @@ -1,3 +1,4 @@ +#if PROTOBUF using System; using WireMock.Models; @@ -36,4 +37,5 @@ private MatchResult GetMatchResult(IRequestMessage requestMessage) { return Matcher?.IsMatchAsync(requestMessage.BodyAsBytes).GetAwaiter().GetResult() ?? default; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.ProtoBuf/Properties/AssemblyInfo.cs b/src/WireMock.Net.ProtoBuf/Properties/AssemblyInfo.cs index ee5b32150..a2f9571eb 100644 --- a/src/WireMock.Net.ProtoBuf/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net.ProtoBuf/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] // Needed for Moq in the UnitTest project -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file +// [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net.ProtoBuf/RequestBuilders/IRequestBuilderExtensions.cs b/src/WireMock.Net.ProtoBuf/RequestBuilders/IProtoBufRequestBuilderExtensions.cs similarity index 96% rename from src/WireMock.Net.ProtoBuf/RequestBuilders/IRequestBuilderExtensions.cs rename to src/WireMock.Net.ProtoBuf/RequestBuilders/IProtoBufRequestBuilderExtensions.cs index dcf63c538..66e769395 100644 --- a/src/WireMock.Net.ProtoBuf/RequestBuilders/IRequestBuilderExtensions.cs +++ b/src/WireMock.Net.ProtoBuf/RequestBuilders/IProtoBufRequestBuilderExtensions.cs @@ -1,3 +1,4 @@ +#if PROTOBUF // ReSharper disable InconsistentNaming using Stef.Validation; using WireMock.Matchers; @@ -6,9 +7,9 @@ namespace WireMock.RequestBuilders; /// -/// IRequestBuilderExtensions extensions for GraphQL. +/// IRequestBuilderExtensions extensions for ProtoBuf. /// -public static class IRequestBuilderExtensions +public static class IProtoBufRequestBuilderExtensions { /// /// WithGrpcProto @@ -61,4 +62,5 @@ public static IRequestBuilder WithBodyAsProtoBuf(this IRequestBuilder requestBui { return Guard.NotNull(requestBuilder).Add(new RequestMessageProtoBufMatcher(matchBehaviour, () => requestBuilder.Mapping.ProtoDefinition!.Value, messageType, matcher)); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.ProtoBuf/Util/ProtoBufUtils.cs b/src/WireMock.Net.ProtoBuf/Util/ProtoBufUtils.cs index b3b355758..958ff9c42 100644 --- a/src/WireMock.Net.ProtoBuf/Util/ProtoBufUtils.cs +++ b/src/WireMock.Net.ProtoBuf/Util/ProtoBufUtils.cs @@ -1,3 +1,4 @@ +#if PROTOBUF using System; using System.Threading; using System.Threading.Tasks; @@ -36,4 +37,5 @@ public async Task GetProtoBufMessageWithHeaderAsync( return await SingletonFactory.GetInstance().ConvertAsync(request, cancellationToken).ConfigureAwait(false); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj b/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj index e7de51fd0..eb0102e11 100644 --- a/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj +++ b/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj @@ -30,7 +30,7 @@ - + \ No newline at end of file diff --git a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj index 10163956b..901e34a29 100644 --- a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj +++ b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj @@ -3,7 +3,7 @@ Lightweight StandAlone Http Mocking Server for .NET which includes GraphQL-support, ProtoBuf-support, MimePartMatcher and CSharpCodeMatcher. WireMock.Net.StandAlone Stef Heyenrath - net451;net452;net46;net461;net462;net47;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + net451;net452;net46;net461;net462;net47;net48;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0 true WireMock.Net.StandAlone WireMock.Net.StandAlone @@ -15,7 +15,7 @@ true true true - WireMock.Net.StandAlone.ruleset + ../WireMock.Net/WireMock.Net.ruleset true ../WireMock.Net/WireMock.Net.snk @@ -40,22 +40,6 @@ - - - - - - - - - - - - - - - - diff --git a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.ruleset b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.ruleset deleted file mode 100644 index 978d27ca3..000000000 --- a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.ruleset +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs index 7ffae3501..66127243a 100644 --- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs +++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs @@ -144,8 +144,6 @@ private Task RunHost(CancellationToken token) _logger.Info("Server using .NET 5.0"); #elif NET6_0 _logger.Info("Server using .NET 6.0"); -#elif NET7_0 - _logger.Info("Server using .NET 7.0"); #elif NET8_0 _logger.Info("Server using .NET 8.0"); #elif NET46 diff --git a/src/WireMock.Net/Properties/AssemblyInfo.cs b/src/WireMock.Net/Properties/AssemblyInfo.cs index aa14015b8..cd3be9eb8 100644 --- a/src/WireMock.Net/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net/Properties/AssemblyInfo.cs @@ -1,9 +1,9 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("WireMock.Net.ProtoBuf, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] -[assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] -[assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] -[assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.ProtoBuf, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index e80e1cfe9..a352a326c 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -54,6 +54,26 @@ $(DefineConstants);TRAILINGHEADERS + + $(DefineConstants);GRAPHQL + true + + + + $(DefineConstants);MIMEKIT + true + + + + $(DefineConstants);PROTOBUF + true + + + + $(DefineConstants);CSHARPMATCHER + true + + @@ -145,10 +165,6 @@ - - all @@ -192,4 +208,44 @@ + + + + %(RecursiveDir)/%(FileName)%(Extension) + + + %(RecursiveDir)/%(FileName)%(Extension) + + + %(RecursiveDir)/%(FileName)%(Extension) + + + %(RecursiveDir)/%(FileName)%(Extension) + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj index 4fa56a8e8..884eeb396 100644 --- a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj +++ b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj @@ -21,10 +21,6 @@ - - - - diff --git a/test/WireMock.Net.Tests/AdminApi/WireMockAdminApiTests.GetMappingsAsync.cs b/test/WireMock.Net.Tests/AdminApi/WireMockAdminApiTests.GetMappingsAsync.cs index 637db397b..de26bccba 100644 --- a/test/WireMock.Net.Tests/AdminApi/WireMockAdminApiTests.GetMappingsAsync.cs +++ b/test/WireMock.Net.Tests/AdminApi/WireMockAdminApiTests.GetMappingsAsync.cs @@ -1,4 +1,4 @@ -#if !(NET452 || NET461 || NETCOREAPP3_1) +#if PROTOBUF using System.Threading.Tasks; using RestEase; using VerifyXunit; diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj index 18340ab3e..2178b0233 100644 --- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj +++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj @@ -2,7 +2,7 @@ Stef Heyenrath - net452;net461;netcoreapp3.1;net6.0;net7.0;net8.0 + net452;net461;netcoreapp3.1;net6.0;net8.0 11 enable false @@ -26,36 +26,34 @@ NETFRAMEWORK - - $(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF + + $(DefineConstants);GRAPHQL + true + + + + $(DefineConstants);MIMEKIT + true + + + + $(DefineConstants);PROTOBUF + true $(DefineConstants);TRAILINGHEADERS - - + - @@ -119,7 +117,7 @@ - + From 919351b0abb80a87b40454c4283ba02ed03b54be Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 2 Mar 2024 16:59:25 +0100 Subject: [PATCH 09/20] 7 --- src/WireMock.Net/WireMock.Net.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index a352a326c..1a3e7a8b5 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -3,7 +3,7 @@ Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape. WireMock.Net Stef Heyenrath - net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0 + net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0 true WireMock.Net WireMock.Net @@ -38,7 +38,7 @@ $(DefineConstants);NETSTANDARD;USE_ASPNETCORE - + $(DefineConstants);USE_ASPNETCORE @@ -54,7 +54,7 @@ $(DefineConstants);TRAILINGHEADERS - + $(DefineConstants);GRAPHQL true @@ -160,7 +160,7 @@ - + @@ -245,7 +245,7 @@ - + \ No newline at end of file From 3d3f57cfcb4d6bf9f5a0f584d16d369a181a349c Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 2 Mar 2024 17:07:17 +0100 Subject: [PATCH 10/20] test --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2b2c5826..f6bb06026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ + # 1.5.48 (17 February 2024) - [#1047](https://github.com/WireMock-Net/WireMock.Net/pull/1047) - Add Grpc ProtoBuf support (request-response) [feature] contributed by [StefH](https://github.com/StefH) - [#1058](https://github.com/WireMock-Net/WireMock.Net/pull/1058) - Fix some SonarCloud issues [refactor] contributed by [StefH](https://github.com/StefH) From c0f46a700bd1c9ec782d83bb34a6db22b1b968c6 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 2 Mar 2024 17:14:43 +0100 Subject: [PATCH 11/20] 8 --- .github/workflows/ci.yml | 10 ++++------ WireMock.Net Solution.sln | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7bb91847b..f8d8bb6ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,16 +21,15 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: | - 7.0.x 8.0.x - name: 'Build Unit Tests' run: | - dotnet build './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0 + dotnet build './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 - name: 'Run Unit Tests' run: | - dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0 + dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 linux-build-and-run: runs-on: ubuntu-latest @@ -44,13 +43,12 @@ jobs: - uses: actions/setup-dotnet@v3 with: dotnet-version: | - 7.0.x 8.0.x - name: 'Build Unit Tests' run: | - dotnet build './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0 + dotnet build './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 - name: 'Run Unit Tests' run: | - dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0 \ No newline at end of file + dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0 \ No newline at end of file diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index bfc0bbdbd..4736f80ea 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -70,7 +70,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net472 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{1DAEFF47-D117-4E95-8B3E-4F7C8B92011A}" ProjectSection(SolutionItems) = preProject - ..\System.Linq.Dynamic.Core\.github\workflows\ci.yml = ..\System.Linq.Dynamic.Core\.github\workflows\ci.yml + .github\workflows\ci.yml = .github\workflows\ci.yml .github\workflows\CreateRelease.yml = .github\workflows\CreateRelease.yml EndProjectSection EndProject From be19ef03dc54b9e9a476651ec2f502ec7a1d968b Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Tue, 9 Jul 2024 19:51:07 +0200 Subject: [PATCH 12/20] fix --- .../Request/RequestMessageMultiPartMatcher.cs | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs b/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs index 572e419bd..896a1c987 100644 --- a/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs +++ b/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs @@ -1,6 +1,7 @@ +#if MIMEKIT using System; -using System.Collections.Generic; using System.Linq; +using MimeKit; using Stef.Validation; using WireMock.Util; @@ -9,16 +10,12 @@ namespace WireMock.Matchers.Request; /// /// The request body MultiPart matcher. /// -public class RequestMessageMultiPartMatcher : IRequestMatcher +public class RequestMessageMultiPartMatcher : IRequestMessageMultiPartMatcher { - /// - /// The matchers. - /// + /// public IMatcher[]? Matchers { get; } - /// - /// The - /// + /// public MatchOperator MatchOperator { get; } = MatchOperator.Or; /// @@ -26,6 +23,8 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher /// public MatchBehaviour MatchBehaviour { get; } + private readonly MimeKitUtils _mimeKitUtils = new(); + /// /// Initializes a new instance of the class. /// @@ -51,9 +50,6 @@ public RequestMessageMultiPartMatcher(MatchBehaviour matchBehaviour, MatchOperat /// public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) { -#if !MIMEKIT - throw new System.NotSupportedException("The MultiPartMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower."); -#else var score = MatchScores.Mismatch; Exception? exception = null; @@ -62,19 +58,17 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu return requestMatchResult.AddScore(GetType(), score, null); } - if (!MimeKitUtils.TryGetMimeMessage(requestMessage, out var message)) + if (!_mimeKitUtils.TryGetMimeMessage(requestMessage, out MimeMessage? message)) { return requestMatchResult.AddScore(GetType(), score, null); } try { - var mimePartMatchers = Matchers.OfType().ToArray(); - foreach (var mimePartMatcher in Matchers.OfType().ToArray()) { score = MatchScores.Mismatch; - foreach (var mimeBodyPart in message.BodyParts.OfType()) + foreach (var mimeBodyPart in message.BodyParts.OfType()) { var matchResult = mimePartMatcher.IsMatch(mimeBodyPart); if (matchResult.IsPerfect()) @@ -83,6 +77,7 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu break; } } + if ((MatchOperator == MatchOperator.Or && MatchScores.IsPerfect(score)) || (MatchOperator == MatchOperator.And && !MatchScores.IsPerfect(score))) { @@ -96,6 +91,6 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu } return requestMatchResult.AddScore(GetType(), score, exception); -#endif } -} \ No newline at end of file +} +#endif \ No newline at end of file From d727645b8e8fa3935ff8925e5d55de769aa9ba7f Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 10 Jul 2024 20:38:01 +0200 Subject: [PATCH 13/20] 1.6.0-preview-00 --- Directory.Build.props | 2 +- src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj | 1 + src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj | 1 + src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 16a6b3ee7..2c24b6041 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.5.60 + 1.5.60 WireMock.Net-Logo.png https://github.com/WireMock-Net/WireMock.Net Apache-2.0 diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj index 5a52a1d79..38eb774a3 100644 --- a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -1,6 +1,7 @@ + 1.6.0-preview-00 GraphQL support for WireMock.Net WireMock.Net.Matchers.GraphQL Stef Heyenrath diff --git a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj index 9f6c9be9a..98353deb7 100644 --- a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj +++ b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj @@ -1,6 +1,7 @@ + 1.6.0-preview-00 MultiPart Mime support for WireMock.Net WireMock.Net.MimeKitLite Stef Heyenrath diff --git a/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj b/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj index 79e9a84ba..67e99b964 100644 --- a/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj +++ b/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj @@ -1,6 +1,7 @@ + 1.6.0-preview-00 ProtoBuf and gRPC support for WireMock.Net WireMock.Net.ProtoBuf Stef Heyenrath From 6ac2018c1e72f2a1b308f47e155d1d7e3333e258 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 10 Jul 2024 20:39:57 +0200 Subject: [PATCH 14/20] . --- .../Matchers/CSharpCodeMatcher.cs | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs index 4fa6ec044..934f323a4 100644 --- a/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs +++ b/src/WireMock.Net.Matchers.CSharpCode/Matchers/CSharpCodeMatcher.cs @@ -1,4 +1,3 @@ -//#if CSHARPMATCHER using System; using System.Linq; using System.Reflection; @@ -145,24 +144,24 @@ private bool IsMatch(dynamic input, string pattern) } } #elif (NET46 || NET461) - dynamic script; - try - { - script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*"); - } - catch (Exception ex) - { - throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex); - } - - try - { - result = script.IsMatch(inputValue); - } - catch (Exception ex) - { - throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); - } + dynamic script; + try + { + script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*"); + } + catch (Exception ex) + { + throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex); + } + + try + { + result = script.IsMatch(inputValue); + } + catch (Exception ex) + { + throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); + } #elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0_OR_GREATER) Assembly assembly; @@ -194,7 +193,7 @@ private bool IsMatch(dynamic input, string pattern) throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex); } #else - throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3"); + throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3"); #endif try { @@ -232,5 +231,4 @@ public AnyOf[] GetPatterns() /// public string Name => nameof(CSharpCodeMatcher); -} -//#endif \ No newline at end of file +} \ No newline at end of file From 8df38dbee54df1c71c0b96fd78e6944f3f5ea6b0 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 10 Jul 2024 20:52:27 +0200 Subject: [PATCH 15/20] . --- src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj index a5286e6ea..c59f8e353 100644 --- a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj +++ b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj @@ -1,5 +1,6 @@ + 1.6.0-preview-00 Minimal version for WireMock.Net WireMock.Net.Minimal Stef Heyenrath From 65d01e6cc45d87bc131dd78ece63a06e3181e066 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 10 Jul 2024 20:54:31 +0200 Subject: [PATCH 16/20] min --- Directory.Build.props | 2 +- .../WireMock.Net.GraphQL.csproj | 1 - .../WireMock.Net.MimeKitLite.csproj | 1 - .../WireMock.Net.Minimal.csproj | 32 ------------------- 4 files changed, 1 insertion(+), 35 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 2c24b6041..b5a990633 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.5.60 + 1.6.0 WireMock.Net-Logo.png https://github.com/WireMock-Net/WireMock.Net Apache-2.0 diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj index 38eb774a3..5a52a1d79 100644 --- a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -1,7 +1,6 @@ - 1.6.0-preview-00 GraphQL support for WireMock.Net WireMock.Net.Matchers.GraphQL Stef Heyenrath diff --git a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj index 98353deb7..9f6c9be9a 100644 --- a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj +++ b/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj @@ -1,7 +1,6 @@ - 1.6.0-preview-00 MultiPart Mime support for WireMock.Net WireMock.Net.MimeKitLite Stef Heyenrath diff --git a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj index c59f8e353..851afe331 100644 --- a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj +++ b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj @@ -1,6 +1,5 @@ - 1.6.0-preview-00 Minimal version for WireMock.Net WireMock.Net.Minimal Stef Heyenrath @@ -22,12 +21,7 @@ true - - - - - true @@ -56,13 +50,7 @@ - - @@ -157,10 +145,6 @@ - - all @@ -186,20 +170,4 @@ - - - - - - - - \ No newline at end of file From 2c25fde7dc71f4bca3ea8eb020b2a0f858be2200 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Wed, 10 Jul 2024 20:56:27 +0200 Subject: [PATCH 17/20] 804 --- src/dotnet-WireMock.Net/dotnet-WireMock.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj index 884eeb396..23bf2b910 100644 --- a/src/dotnet-WireMock.Net/dotnet-WireMock.csproj +++ b/src/dotnet-WireMock.Net/dotnet-WireMock.csproj @@ -17,7 +17,7 @@ - + From c0045e642c365cc58796dad334b7703b1c295ec1 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 27 Jul 2024 15:29:17 +0200 Subject: [PATCH 18/20] rename to MimePart --- README.md | 1 + WireMock.Net Solution.sln | 2 +- src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs | 6 ------ .../Matchers/MimePartMatcher.cs | 0 .../Matchers/Request/RequestMessageMultiPartMatcher.cs | 0 src/WireMock.Net.MimePart/Properties/AssemblyInfo.cs | 0 .../RequestBuilders/IMultiPartRequestBuilderExtensions.cs | 0 .../Util/MimeKitUtils.cs | 0 .../WireMock.Net.MimePart.csproj} | 2 +- src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs | 2 +- src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj | 2 +- src/WireMock.Net/Properties/AssemblyInfo.cs | 2 +- src/WireMock.Net/WireMock.Net.csproj | 2 +- 13 files changed, 7 insertions(+), 12 deletions(-) delete mode 100644 src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs rename src/{WireMock.Net.MimeKitLite => WireMock.Net.MimePart}/Matchers/MimePartMatcher.cs (100%) rename src/{WireMock.Net.MimeKitLite => WireMock.Net.MimePart}/Matchers/Request/RequestMessageMultiPartMatcher.cs (100%) create mode 100644 src/WireMock.Net.MimePart/Properties/AssemblyInfo.cs rename src/{WireMock.Net.MimeKitLite => WireMock.Net.MimePart}/RequestBuilders/IMultiPartRequestBuilderExtensions.cs (100%) rename src/{WireMock.Net.MimeKitLite => WireMock.Net.MimePart}/Util/MimeKitUtils.cs (100%) rename src/{WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj => WireMock.Net.MimePart/WireMock.Net.MimePart.csproj} (96%) diff --git a/README.md b/README.md index 8c1d0bac9..b9112fdfa 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co | | Info | Official | Preview [:information_source:](https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions) | | - | - | - | |   **WireMock.Net** | Main project | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net)](https://www.nuget.org/packages/WireMock.Net) | [![MyGet Badge WireMock.Net](https://buildstats.info/myget/wiremock-net/WireMock.Net?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net) +|   **WireMock.Net.Minimal** | Minimal project
Does not include:
- GraphQL
- MimePart
- Protobuf| [![NuGet Badge WireMock.Net.Minimal](https://buildstats.info/nuget/WireMock.Net.Minimal)](https://www.nuget.org/packages/WireMock.Net.Minimal) | [![MyGet Badge WireMock.Net](https://buildstats.info/myget/wiremock-net/WireMock.Net.Minimal?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Minimal) |   **WireMock.Net.StandAlone** | StandAlone | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net.StandAlone)](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [![MyGet Badge WireMock.Net.StandAlone](https://buildstats.info/myget/wiremock-net/WireMock.Net.StandAlone?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone) |   **WireMock.Net.GraphQL** | [GraphQL Support](https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-GraphQLMatcher) | [![NuGet Badge WireMock.Net.GraphQL](https://buildstats.info/nuget/WireMock.Net.GraphQL)](https://www.nuget.org/packages/WireMock.Net.GraphQL) | [![MyGet Badge WireMock.Net.GraphQL](https://buildstats.info/myget/wiremock-net/WireMock.Net.GraphQL?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.GraphQL) |   **WireMock.Net.MimeKitLite** | [MimePart Support](https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-MimePartMatcher) | [![NuGet Badge WireMock.Net.MimeKitLite](https://buildstats.info/nuget/WireMock.Net.MimeKitLite)](https://www.nuget.org/packages/WireMock.Net.MimeKitLite) | [![MyGet Badge WireMock.Net.MimeKitLite](https://buildstats.info/myget/wiremock-net/WireMock.Net.MimeKitLite?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.MimeKitLite) diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 996eb72f4..f4722c3a5 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -115,7 +115,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.GrpcCl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.GraphQL", "src\WireMock.Net.GraphQL\WireMock.Net.GraphQL.csproj", "{B6269AAC-170A-4346-8B9A-444DED3D9A45}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.MimeKitLite", "src\WireMock.Net.MimeKitLite\WireMock.Net.MimeKitLite.csproj", "{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.MimePart", "src\WireMock.Net.MimePart\WireMock.Net.MimePart.csproj", "{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.ProtoBuf", "src\WireMock.Net.ProtoBuf\WireMock.Net.ProtoBuf.csproj", "{B47413AA-55D3-49A7-896A-17ADBFF72407}" EndProject diff --git a/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs b/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs deleted file mode 100644 index a2f9571eb..000000000 --- a/src/WireMock.Net.MimeKitLite/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System.Runtime.CompilerServices; - -// [assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] - -// Needed for Moq in the UnitTest project -// [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs b/src/WireMock.Net.MimePart/Matchers/MimePartMatcher.cs similarity index 100% rename from src/WireMock.Net.MimeKitLite/Matchers/MimePartMatcher.cs rename to src/WireMock.Net.MimePart/Matchers/MimePartMatcher.cs diff --git a/src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs b/src/WireMock.Net.MimePart/Matchers/Request/RequestMessageMultiPartMatcher.cs similarity index 100% rename from src/WireMock.Net.MimeKitLite/Matchers/Request/RequestMessageMultiPartMatcher.cs rename to src/WireMock.Net.MimePart/Matchers/Request/RequestMessageMultiPartMatcher.cs diff --git a/src/WireMock.Net.MimePart/Properties/AssemblyInfo.cs b/src/WireMock.Net.MimePart/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e69de29bb diff --git a/src/WireMock.Net.MimeKitLite/RequestBuilders/IMultiPartRequestBuilderExtensions.cs b/src/WireMock.Net.MimePart/RequestBuilders/IMultiPartRequestBuilderExtensions.cs similarity index 100% rename from src/WireMock.Net.MimeKitLite/RequestBuilders/IMultiPartRequestBuilderExtensions.cs rename to src/WireMock.Net.MimePart/RequestBuilders/IMultiPartRequestBuilderExtensions.cs diff --git a/src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs b/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs similarity index 100% rename from src/WireMock.Net.MimeKitLite/Util/MimeKitUtils.cs rename to src/WireMock.Net.MimePart/Util/MimeKitUtils.cs diff --git a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj b/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj similarity index 96% rename from src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj rename to src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj index 9f6c9be9a..53e126654 100644 --- a/src/WireMock.Net.MimeKitLite/WireMock.Net.MimeKitLite.csproj +++ b/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj @@ -2,7 +2,7 @@ MultiPart Mime support for WireMock.Net - WireMock.Net.MimeKitLite + WireMock.Net.MimePart Stef Heyenrath netstandard2.0;netstandard2.1;net462;net47;net48;net6.0;net8.0 true diff --git a/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs b/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs index 1d42700e7..fb89b63e1 100644 --- a/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net.Minimal/Properties/AssemblyInfo.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("WireMock.Net.ProtoBuf, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] -[assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +[assembly: InternalsVisibleTo("WireMock.Net.MimePart, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] //[assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj index 3221225e8..cece4436d 100644 --- a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj +++ b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/WireMock.Net/Properties/AssemblyInfo.cs b/src/WireMock.Net/Properties/AssemblyInfo.cs index 924bdc771..05ea5ad04 100644 --- a/src/WireMock.Net/Properties/AssemblyInfo.cs +++ b/src/WireMock.Net/Properties/AssemblyInfo.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; // [assembly: InternalsVisibleTo("WireMock.Net.ProtoBuf, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] -// [assembly: InternalsVisibleTo("WireMock.Net.MimeKitLite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] +// [assembly: InternalsVisibleTo("WireMock.Net.MimePart, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] // [assembly: InternalsVisibleTo("WireMock.Net.GraphQL, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] // [assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] [assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")] diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj index 9aba8eb3c..fdf005751 100644 --- a/src/WireMock.Net/WireMock.Net.csproj +++ b/src/WireMock.Net/WireMock.Net.csproj @@ -214,7 +214,7 @@ %(RecursiveDir)/%(FileName)%(Extension) - + %(RecursiveDir)/%(FileName)%(Extension) From 62f07c8d00c00062264b53f61a6754c869a74f19 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 27 Jul 2024 16:09:02 +0200 Subject: [PATCH 19/20] ...................................... --- WireMock.Net Solution.sln | 11 + .../Exceptions/WireMockException.cs | 36 ++++ .../Extensions/AnyOfExtensions.cs | 44 ++++ .../Extensions/ExceptionExtensions.cs | 18 ++ src/WireMock.Net.Common/IMapping.cs | 200 ++++++++++++++++++ .../Matchers/IGraphQLMatcher.cs | 16 ++ src/WireMock.Net.Common/Matchers/IMatcher.cs | 19 ++ .../Matchers/IStringMatcher.cs | 31 +++ .../Matchers/MatchBehaviour.cs | 19 ++ .../Matchers/MatchBehaviourHelper.cs | 35 +++ .../Matchers/MatchOperator.cs | 24 +++ .../Matchers/MatchResult.cs | 91 ++++++++ .../Matchers/MatchScores.cs | 85 ++++++++ .../Request/IRequestMessageGraphQLMatcher.cs | 17 ++ .../Models/GraphQLSchemaDetails.cs | 61 ++++++ .../Models/StringPattern.cs | 19 ++ .../RequestBuilders/IBodyRequestBuilder.cs | 97 +++++++++ .../IClientIPRequestBuilder.cs | 49 +++++ .../RequestBuilders/ICookiesRequestBuilder.cs | 85 ++++++++ .../RequestBuilders/IHeadersRequestBuilder.cs | 88 ++++++++ .../RequestBuilders/IHttpVersionBuilder.cs | 20 ++ .../RequestBuilders/IMethodRequestBuilder.cs | 96 +++++++++ .../RequestBuilders/IParamsRequestBuilder.cs | 110 ++++++++++ .../RequestBuilders/IRequestBuilder.cs | 18 ++ .../IUrlAndPathRequestBuilder.cs | 86 ++++++++ .../RequestBuilders/Request.ClientIP.cs | 50 +++++ .../RequestBuilders/Request.UsingMethods.cs | 104 +++++++++ .../RequestBuilders/Request.WithBody.cs | 100 +++++++++ .../RequestBuilders/Request.WithCookies.cs | 83 ++++++++ .../RequestBuilders/Request.WithHeaders.cs | 85 ++++++++ .../Request.WithHttpVersion.cs | 15 ++ .../RequestBuilders/Request.WithParam.cs | 93 ++++++++ .../RequestBuilders/Request.WithPath.cs | 50 +++++ .../RequestBuilders/Request.WithUrl.cs | 50 +++++ .../RequestBuilders/Request.cs | 83 ++++++++ .../Util/ReflectionUtils.cs | 50 +++++ src/WireMock.Net.Common/Util/TypeLoader.cs | 95 +++++++++ .../WireMock.Net.Common.csproj | 100 +++++++++ .../Matchers/GraphQLMatcher.cs | 4 +- .../Models/WireMockCustomScalarGraphType.cs | 4 +- .../Request/RequestMessageGraphQLMatcher.cs | 4 +- .../IGraphQLRequestBuilderExtensions.cs | 4 +- .../WireMock.Net.GraphQL.csproj | 15 +- .../WireMock.Net.MimePart.csproj | 2 - .../WireMock.Net.ProtoBuf.csproj | 2 - 45 files changed, 2353 insertions(+), 15 deletions(-) create mode 100644 src/WireMock.Net.Common/Exceptions/WireMockException.cs create mode 100644 src/WireMock.Net.Common/Extensions/AnyOfExtensions.cs create mode 100644 src/WireMock.Net.Common/Extensions/ExceptionExtensions.cs create mode 100644 src/WireMock.Net.Common/IMapping.cs create mode 100644 src/WireMock.Net.Common/Matchers/IGraphQLMatcher.cs create mode 100644 src/WireMock.Net.Common/Matchers/IMatcher.cs create mode 100644 src/WireMock.Net.Common/Matchers/IStringMatcher.cs create mode 100644 src/WireMock.Net.Common/Matchers/MatchBehaviour.cs create mode 100644 src/WireMock.Net.Common/Matchers/MatchBehaviourHelper.cs create mode 100644 src/WireMock.Net.Common/Matchers/MatchOperator.cs create mode 100644 src/WireMock.Net.Common/Matchers/MatchResult.cs create mode 100644 src/WireMock.Net.Common/Matchers/MatchScores.cs create mode 100644 src/WireMock.Net.Common/Matchers/Request/IRequestMessageGraphQLMatcher.cs create mode 100644 src/WireMock.Net.Common/Models/GraphQLSchemaDetails.cs create mode 100644 src/WireMock.Net.Common/Models/StringPattern.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IBodyRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IClientIPRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/ICookiesRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IHeadersRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IHttpVersionBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IMethodRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IParamsRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/IUrlAndPathRequestBuilder.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.ClientIP.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.UsingMethods.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithBody.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithCookies.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithHeaders.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithHttpVersion.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithParam.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithPath.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.WithUrl.cs create mode 100644 src/WireMock.Net.Common/RequestBuilders/Request.cs create mode 100644 src/WireMock.Net.Common/Util/ReflectionUtils.cs create mode 100644 src/WireMock.Net.Common/Util/TypeLoader.cs create mode 100644 src/WireMock.Net.Common/WireMock.Net.Common.csproj diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index f4722c3a5..fd71d1029 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -121,6 +121,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.ProtoBuf", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Minimal", "src\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj", "{A39C689E-B94B-4BBB-A270-B5A4C2B6D179}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Common", "src\WireMock.Net.Common\WireMock.Net.Common.csproj", "{CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -457,6 +459,14 @@ Global {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Release|Any CPU.Build.0 = Release|Any CPU {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Release|x64.ActiveCfg = Release|Any CPU {A39C689E-B94B-4BBB-A270-B5A4C2B6D179}.Release|x64.Build.0 = Release|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Debug|x64.ActiveCfg = Debug|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Debug|x64.Build.0 = Debug|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Release|Any CPU.Build.0 = Release|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Release|x64.ActiveCfg = Release|Any CPU + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -505,6 +515,7 @@ Global {F8B4A93E-46EF-4237-88FE-15FDAB7635D4} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} {B47413AA-55D3-49A7-896A-17ADBFF72407} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} {A39C689E-B94B-4BBB-A270-B5A4C2B6D179} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} + {CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} diff --git a/src/WireMock.Net.Common/Exceptions/WireMockException.cs b/src/WireMock.Net.Common/Exceptions/WireMockException.cs new file mode 100644 index 000000000..ce68e8cfc --- /dev/null +++ b/src/WireMock.Net.Common/Exceptions/WireMockException.cs @@ -0,0 +1,36 @@ +// Copyright © WireMock.Net + +using System; + +namespace WireMock.Exceptions; + +/// +/// WireMockException +/// +/// +public class WireMockException : Exception +{ + /// + /// Initializes a new instance of the class. + /// + public WireMockException() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public WireMockException(string message) : base(message) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// The inner. + public WireMockException(string message, Exception inner) : base(message, inner) + { + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Extensions/AnyOfExtensions.cs b/src/WireMock.Net.Common/Extensions/AnyOfExtensions.cs new file mode 100644 index 000000000..a97adb38d --- /dev/null +++ b/src/WireMock.Net.Common/Extensions/AnyOfExtensions.cs @@ -0,0 +1,44 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; +using System.Linq; +using AnyOfTypes; +using WireMock.Models; + +namespace WireMock.Extensions; + +/// +/// Some extensions for AnyOf. +/// +public static class AnyOfExtensions +{ + /// + /// Gets the pattern. + /// + /// AnyOf type + /// string value + public static string GetPattern(this AnyOf value) + { + return value.IsFirst ? value.First : value.Second.Pattern; + } + + /// + /// Converts a string-patterns to AnyOf patterns. + /// + /// The string patterns + /// The AnyOf patterns + public static AnyOf[] ToAnyOfPatterns(this IEnumerable patterns) + { + return patterns.Select(p => p.ToAnyOfPattern()).ToArray(); + } + + /// + /// Converts a string-pattern to AnyOf pattern. + /// + /// The string pattern + /// The AnyOf pattern + public static AnyOf ToAnyOfPattern(this string pattern) + { + return new AnyOf(pattern); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Extensions/ExceptionExtensions.cs b/src/WireMock.Net.Common/Extensions/ExceptionExtensions.cs new file mode 100644 index 000000000..60069db40 --- /dev/null +++ b/src/WireMock.Net.Common/Extensions/ExceptionExtensions.cs @@ -0,0 +1,18 @@ +// Copyright © WireMock.Net + +using System; + +namespace WireMock.Extensions; + +public static class ExceptionExtensions +{ + public static Exception? ToException(this Exception[] exceptions) + { + return exceptions.Length switch + { + 1 => exceptions[0], + > 1 => new AggregateException(exceptions), + _ => null + }; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/IMapping.cs b/src/WireMock.Net.Common/IMapping.cs new file mode 100644 index 000000000..671029989 --- /dev/null +++ b/src/WireMock.Net.Common/IMapping.cs @@ -0,0 +1,200 @@ +// Copyright © WireMock.Net + +using System; +using System.Threading.Tasks; +using WireMock.Matchers.Request; +using WireMock.Models; +using WireMock.ResponseProviders; +using WireMock.Settings; + +namespace WireMock; + +/// +/// The IMapping interface. +/// +public interface IMapping +{ + /// + /// Gets the unique identifier. + /// + Guid Guid { get; } + + /// + /// The datetime when this mapping was created or updated. + /// + public DateTime? UpdatedAt { get; set; } + + /// + /// Gets the TimeSettings (Start, End and TTL). + /// + ITimeSettings? TimeSettings { get; } + + /// + /// Gets the unique title. + /// + string? Title { get; } + + /// + /// Gets the description. + /// + string? Description { get; } + + /// + /// The full filename path for this mapping (only defined for static mappings). + /// + string? Path { get; set; } + + /// + /// Gets the priority. (A low value means higher priority.) + /// + int Priority { get; } + + /// + /// Scenario. + /// + string? Scenario { get; } + + /// + /// Execution state condition for the current mapping. + /// + string? ExecutionConditionState { get; } + + /// + /// The next state which will be signaled after the current mapping execution. + /// In case the value is null, state will not be changed. + /// + string? NextState { get; } + + /// + /// The number of times this match should be matched before the state will be changed to the next state. + /// + int? StateTimes { get; } + + /// + /// The RequestMatcher. + /// + IRequestMatcher RequestMatcher { get; } + + /// + /// The ResponseProvider. + /// + IResponseProvider Provider { get; } + + /// + /// The WireMockServerSettings. + /// + WireMockServerSettings Settings { get; } + + /// + /// Is State started ? + /// + bool IsStartState { get; } + + /// + /// Gets a value indicating whether this mapping is an Admin Interface. + /// + /// + /// true if this mapping is an Admin Interface; otherwise, false. + /// + bool IsAdminInterface { get; } + + /// + /// Gets a value indicating whether this mapping is a Proxy Mapping. + /// + /// + /// true if this mapping is a Proxy Mapping; otherwise, false. + /// + bool IsProxy { get; } + + /// + /// Gets a value indicating whether this mapping to be logged. + /// + /// + /// true if this mapping to be logged; otherwise, false. + /// + bool LogMapping { get; } + + /// + /// The Webhooks. + /// + IWebhook[]? Webhooks { get; } + + /// + /// Use Fire and Forget for the defined webhook(s). [Optional] + /// + bool? UseWebhooksFireAndForget { get; } + + /// + /// Data Object which can be used when WithTransformer is used. + /// e.g. lookup an path in this object using + /// + /// lookup data "1" + /// + /// + object? Data { get; } + + /// + /// The probability when this request should be matched. Value is between 0 and 1. [Optional] + /// + double? Probability { get; } + + /// + /// The Grpc ProtoDefinition which is used for this mapping (request and response). [Optional] + /// + IdOrText? ProtoDefinition { get; } + + /// + /// ProvideResponseAsync + /// + /// The request message. + /// The including a new (optional) . + Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage); + + /// + /// Gets the RequestMatchResult based on the RequestMessage. + /// + /// The request message. + /// The Next State. + /// The . + IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState); + + /// + /// Define the scenario. + /// + /// The scenario. + /// The . + IMapping WithScenario(string scenario); + + /// + /// Define the probability when this request should be matched. [Optional] + /// + /// The probability. + /// The . + IMapping WithProbability(double probability); + + /// + /// Define a Grpc ProtoDefinition which is used for this mapping (request and response). + /// + /// The proto definition as text. + /// The . + IMapping WithProtoDefinition(IdOrText protoDefinition); +} + +/* + executionConditionState">State in which the current mapping can occur. [Optional] + nextState">The next state which will occur after the current mapping execution. [Optional] + stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional] + webhooks">The Webhooks. [Optional] + useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional] + timeSettings">The TimeSettings. [Optional] + data">The data object. [Optional] + + + string? executionConditionState, + string? nextState, + int? stateTimes, + IWebhook[]? webhooks, + bool? useWebhooksFireAndForget, + ITimeSettings? timeSettings, + object? data, +*/ \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/IGraphQLMatcher.cs b/src/WireMock.Net.Common/Matchers/IGraphQLMatcher.cs new file mode 100644 index 000000000..b7a824143 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/IGraphQLMatcher.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace WireMock.Matchers; + +/// +/// GraphQLMatcher +/// +/// +public interface IGraphQLMatcher : IStringMatcher +{ + /// + /// An optional dictionary defining the custom Scalar and the type. + /// + public IDictionary? CustomScalars { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/IMatcher.cs b/src/WireMock.Net.Common/Matchers/IMatcher.cs new file mode 100644 index 000000000..55eb27ec2 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/IMatcher.cs @@ -0,0 +1,19 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers; + +/// +/// IMatcher +/// +public interface IMatcher +{ + /// + /// Gets the name. + /// + string Name { get; } + + /// + /// Gets the match behaviour. + /// + MatchBehaviour MatchBehaviour { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/IStringMatcher.cs b/src/WireMock.Net.Common/Matchers/IStringMatcher.cs new file mode 100644 index 000000000..bd0f6d515 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/IStringMatcher.cs @@ -0,0 +1,31 @@ +// Copyright © WireMock.Net + +using AnyOfTypes; +using WireMock.Models; + +namespace WireMock.Matchers; + +/// +/// IStringMatcher +/// +/// +public interface IStringMatcher : IMatcher +{ + /// + /// Determines whether the specified input is match. + /// + /// The input. + /// MatchResult + MatchResult IsMatch(string? input); + + /// + /// Gets the patterns. + /// + /// Patterns + AnyOf[] GetPatterns(); + + /// + /// The . + /// + MatchOperator MatchOperator { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/MatchBehaviour.cs b/src/WireMock.Net.Common/Matchers/MatchBehaviour.cs new file mode 100644 index 000000000..1c8fda307 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/MatchBehaviour.cs @@ -0,0 +1,19 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers; + +/// +/// MatchBehaviour (Accept or Reject) +/// +public enum MatchBehaviour +{ + /// + /// Accept on match (default) + /// + AcceptOnMatch, + + /// + /// Reject on match + /// + RejectOnMatch +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/MatchBehaviourHelper.cs b/src/WireMock.Net.Common/Matchers/MatchBehaviourHelper.cs new file mode 100644 index 000000000..40b696e37 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/MatchBehaviourHelper.cs @@ -0,0 +1,35 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers; + +public static class MatchBehaviourHelper +{ + /// + /// Converts the specified match behaviour and match value to a new match value. + /// + /// if AcceptOnMatch --> return match (default) + /// if RejectOnMatch and match = 0.0 --> return 1.0 + /// if RejectOnMatch and match = 0.? --> return 0.0 + /// if RejectOnMatch and match = 1.0 --> return 0.0 + /// + /// + /// The match behaviour. + /// The match. + /// match value + public static double Convert(MatchBehaviour matchBehaviour, double match) + { + if (matchBehaviour == MatchBehaviour.AcceptOnMatch) + { + return match; + } + + return match <= MatchScores.Tolerance ? MatchScores.Perfect : MatchScores.Mismatch; + } + + public static MatchResult Convert(MatchBehaviour matchBehaviour, MatchResult result) + { + return matchBehaviour == MatchBehaviour.AcceptOnMatch ? + result : + new MatchResult(Convert(matchBehaviour, result.Score), result.Exception); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/MatchOperator.cs b/src/WireMock.Net.Common/Matchers/MatchOperator.cs new file mode 100644 index 000000000..9e4c306b8 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/MatchOperator.cs @@ -0,0 +1,24 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers; + +/// +/// The Operator to use when multiple patterns are defined. +/// +public enum MatchOperator +{ + /// + /// Only one pattern needs to match. [Default] + /// + Or, + + /// + /// All patterns should match. + /// + And, + + /// + /// The average value from all patterns. + /// + Average +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/MatchResult.cs b/src/WireMock.Net.Common/Matchers/MatchResult.cs new file mode 100644 index 000000000..5419c1ab2 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/MatchResult.cs @@ -0,0 +1,91 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using Stef.Validation; +using WireMock.Extensions; + +namespace WireMock.Matchers; + +/// +/// The MatchResult which contains the score (value between 0.0 - 1.0 of the similarity) and an optional error message. +/// +public struct MatchResult +{ + /// + /// A value between 0.0 - 1.0 of the similarity. + /// + public double Score { get; set; } + + /// + /// The exception message) in case the matching fails. + /// [Optional] + /// + public Exception? Exception { get; set; } + + /// + /// Create a MatchResult + /// + /// A value between 0.0 - 1.0 of the similarity. + /// The exception in case the matching fails. [Optional] + public MatchResult(double score, Exception? exception = null) + { + Score = score; + Exception = exception; + } + + /// + /// Create a MatchResult + /// + /// The exception in case the matching fails. + public MatchResult(Exception exception) + { + Exception = Guard.NotNull(exception); + } + + /// + /// Implicitly converts a double to a MatchResult. + /// + /// The score + public static implicit operator MatchResult(double score) + { + return new MatchResult(score); + } + + /// + /// Is the value a perfect match? + /// + public bool IsPerfect() => MatchScores.IsPerfect(Score); + + /// + /// Create a MatchResult from multiple MatchResults. + /// + /// A list of MatchResults. + /// The MatchOperator + /// MatchResult + public static MatchResult From(IReadOnlyList matchResults, MatchOperator matchOperator) + { + Guard.NotNullOrEmpty(matchResults); + + if (matchResults.Count == 1) + { + return matchResults[0]; + } + + return new MatchResult + { + Score = MatchScores.ToScore(matchResults.Select(r => r.Score).ToArray(), matchOperator), + Exception = matchResults.Select(m => m.Exception).OfType().ToArray().ToException() + }; + } + + /// + /// Expand to Tuple + /// + /// Tuple : Score and Exception + public (double Score, Exception? Exception) Expand() + { + return (Score, Exception); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/MatchScores.cs b/src/WireMock.Net.Common/Matchers/MatchScores.cs new file mode 100644 index 000000000..deeca2d8b --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/MatchScores.cs @@ -0,0 +1,85 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WireMock.Matchers; + +/// +/// MatchScores +/// +public static class MatchScores +{ + /// + /// The tolerance + /// + public const double Tolerance = 0.000001; + + /// + /// The default mismatch score + /// + public const double Mismatch = 0.0; + + /// + /// The default perfect match score + /// + public const double Perfect = 1.0; + + /// + /// The almost perfect match score + /// + public const double AlmostPerfect = 0.99; + + /// + /// Is the value a perfect match? + /// + /// The value. + /// true/false + public static bool IsPerfect(double value) + { + return Math.Abs(value - Perfect) < Tolerance; + } + + /// + /// Convert a bool to the score. + /// + /// if set to true [value]. + /// score + public static double ToScore(bool value) + { + return value ? Perfect : Mismatch; + } + + /// + /// Calculates the score from multiple values. + /// + /// The values. + /// The . + /// average score + public static double ToScore(IReadOnlyCollection values, MatchOperator matchOperator) + { + return ToScore(values.Select(ToScore).ToArray(), matchOperator); + } + + /// + /// Calculates the score from multiple values. + /// + /// The values. + /// + /// average score + public static double ToScore(IReadOnlyCollection values, MatchOperator matchOperator) + { + if (!values.Any()) + { + return Mismatch; + } + + return matchOperator switch + { + MatchOperator.Or => ToScore(values.Any(IsPerfect)), + MatchOperator.And => ToScore(values.All(IsPerfect)), + _ => values.Average() + }; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/Request/IRequestMessageGraphQLMatcher.cs b/src/WireMock.Net.Common/Matchers/Request/IRequestMessageGraphQLMatcher.cs new file mode 100644 index 000000000..37d355eb7 --- /dev/null +++ b/src/WireMock.Net.Common/Matchers/Request/IRequestMessageGraphQLMatcher.cs @@ -0,0 +1,17 @@ +namespace WireMock.Matchers.Request; + +/// +/// The request body GraphQL matcher. +/// +public interface IRequestMessageGraphQLMatcher : IRequestMatcher +{ + /// + /// The matchers. + /// + IMatcher[]? Matchers { get; } + + /// + /// The + /// + MatchOperator MatchOperator { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Models/GraphQLSchemaDetails.cs b/src/WireMock.Net.Common/Models/GraphQLSchemaDetails.cs new file mode 100644 index 000000000..d40d4e6bb --- /dev/null +++ b/src/WireMock.Net.Common/Models/GraphQLSchemaDetails.cs @@ -0,0 +1,61 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using AnyOfTypes; +using Newtonsoft.Json; + +namespace WireMock.Models; + +/// +/// GraphQLSchemaDetails +/// +public class GraphQLSchemaDetails +{ + /// + /// The GraphQL schema as a string. + /// + public string? SchemaAsString { get; set; } + + /// + /// The GraphQL schema as a StringPattern. + /// + public StringPattern? SchemaAsStringPattern { get; set; } + + /// + /// The GraphQL schema as a "GraphQL.Types.ISchema". + /// + public object? SchemaAsISchema { get; set; } + + /// + /// The GraphQL Schema. + /// + [JsonIgnore] + public AnyOf? Schema + { + get + { + if (SchemaAsString != null) + { + return SchemaAsString; + } + + if (SchemaAsStringPattern != null) + { + return SchemaAsStringPattern; + } + + if (SchemaAsISchema != null) + { + return new AnyOf(SchemaAsISchema); + } + + return null; + } + } + + /// + /// The custom Scalars to define for this schema. + /// + public IDictionary? CustomScalars { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Models/StringPattern.cs b/src/WireMock.Net.Common/Models/StringPattern.cs new file mode 100644 index 000000000..908f4c1a1 --- /dev/null +++ b/src/WireMock.Net.Common/Models/StringPattern.cs @@ -0,0 +1,19 @@ +// Copyright © WireMock.Net + +namespace WireMock.Models; + +/// +/// StringPattern which defines the Pattern as a string, and optionally the filepath pattern file. +/// +public struct StringPattern +{ + /// + /// The pattern as string. + /// + public string Pattern { get; set; } + + /// + /// The filepath (optionally) + /// + public string? PatternAsFile { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IBodyRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IBodyRequestBuilder.cs new file mode 100644 index 000000000..33be189c9 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IBodyRequestBuilder.cs @@ -0,0 +1,97 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using JsonConverter.Abstractions; +using WireMock.Matchers; +using WireMock.Util; + +namespace WireMock.RequestBuilders; + +/// +/// The BodyRequestBuilder interface. +/// +public interface IBodyRequestBuilder : IHttpVersionBuilder +{ + /// + /// WithBody: IMatcher + /// + /// The matcher. + /// The . + IRequestBuilder WithBody(IMatcher matcher); + + /// + /// WithBody: IMatcher[] + /// + /// The matchers. + /// The to use. + /// The . + IRequestBuilder WithBody(IMatcher[] matchers, MatchOperator matchOperator = MatchOperator.Or); + + /// + /// WithBody: Body as string + /// + /// The body. + /// The match behaviour. + /// The . + IRequestBuilder WithBody(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithBody: Body as byte[] + /// + /// The body. + /// The match behaviour. + /// The . + IRequestBuilder WithBody(byte[] body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithBody: Body as object + /// + /// The body. + /// The match behaviour [default is AcceptOnMatch]. + /// The . + IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithBodyAsJson: A will be used to match this object. + /// + /// The body. + /// The match behaviour [default is AcceptOnMatch]. + /// A . + IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithBody: func (string) + /// + /// The function. + /// The . + IRequestBuilder WithBody(Func func); + + /// + /// WithBody: func (byte[]) + /// + /// The function. + /// The . + IRequestBuilder WithBody(Func func); + + /// + /// WithBody: func (json object) + /// + /// The function. + /// The . + IRequestBuilder WithBody(Func func); + + /// + /// WithBody: func (BodyData object) + /// + /// The function. + /// The . + IRequestBuilder WithBody(Func func); + + /// + /// WithBody: Body as form-urlencoded values. + /// + /// The form-urlencoded values. + /// The . + IRequestBuilder WithBody(Func?, bool> func); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IClientIPRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IClientIPRequestBuilder.cs new file mode 100644 index 000000000..4955c5a6a --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IClientIPRequestBuilder.cs @@ -0,0 +1,49 @@ +// Copyright © WireMock.Net + +using System; +using WireMock.Matchers; + +namespace WireMock.RequestBuilders; + +/// +/// The IClientIPRequestBuilder interface. +/// +public interface IClientIPRequestBuilder : IUrlAndPathRequestBuilder +{ + /// + /// WithClientIP: add clientIP matching based on IStringMatchers. + /// + /// The matchers. + /// The . + IRequestBuilder WithClientIP(params IStringMatcher[] matchers); + + /// + /// WithClientIP: add clientIP matching based on MatchOperator and IStringMatchers. + /// + /// The to use. + /// The matchers. + /// The . + IRequestBuilder WithClientIP(MatchOperator matchOperator, params IStringMatcher[] matchers); + + /// + /// WithClientIP: add clientIP matching based on clientIPs. + /// + /// The clientIPs. + /// The . + IRequestBuilder WithClientIP(params string[] clientIPs); + + /// + /// WithClientIP: add clientIP matching based on clientIPs , matchBehaviour and MatchOperator. + /// + /// The to use. + /// The clientIPs. + /// The . + IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] clientIPs); + + /// + /// WithClientIP: add clientIP matching based on functions. + /// + /// The clientIP funcs. + /// The . + IRequestBuilder WithClientIP(params Func[] funcs); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/ICookiesRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/ICookiesRequestBuilder.cs new file mode 100644 index 000000000..bd53e3811 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/ICookiesRequestBuilder.cs @@ -0,0 +1,85 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using WireMock.Matchers; + +namespace WireMock.RequestBuilders; + +/// +/// The CookieRequestBuilder interface. +/// +public interface ICookiesRequestBuilder : IParamsRequestBuilder +{ + /// + /// WithCookie: matching based on name, pattern and matchBehaviour. + /// + /// The name. + /// The pattern. + /// The match behaviour. + /// The . + IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour); + + /// + /// WithCookie: matching based on name, pattern, ignoreCase and matchBehaviour. + /// + /// The name. + /// The pattern. + /// Ignore the case from the pattern. + /// The match behaviour. + /// The . + IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithCookie: matching based on name, patterns and matchBehaviour. + /// + /// The name. + /// The patterns. + /// The match behaviour. + /// The . + IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour); + + /// + /// WithCookie: matching based on name, patterns, ignoreCase and matchBehaviour. + /// + /// The name. + /// The patterns. + /// Ignore the case from the pattern. + /// The match behaviour. + /// The . + IRequestBuilder WithCookie(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithCookie: matching based on name and IStringMatcher[]. + /// + /// The name. + /// The matchers. + /// The . + IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers); + + /// + /// WithCookie: matching based on name, ignoreCase and IStringMatcher[]. + /// + /// The name. + /// Ignore the case from the cookie-keys. + /// The matchers. + /// The . + IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers); + + /// + /// WithCookie: matching based on name, ignoreCase, matchBehaviour and IStringMatcher[]. + /// + /// The name. + /// Ignore the case from the cookie-keys. + /// The match behaviour. + /// The matchers. + /// The . + IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers); + + /// + /// WithCookie: matching based on functions. + /// + /// The cookies funcs. + /// The . + IRequestBuilder WithCookie(params Func, bool>[] funcs); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IHeadersRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IHeadersRequestBuilder.cs new file mode 100644 index 000000000..82a03949c --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IHeadersRequestBuilder.cs @@ -0,0 +1,88 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using WireMock.Matchers; + +namespace WireMock.RequestBuilders; + +/// +/// The HeadersRequestBuilder interface. +/// +public interface IHeadersRequestBuilder : ICookiesRequestBuilder +{ + /// + /// WithHeader: matching based on name, pattern and matchBehaviour. + /// + /// The name. + /// The pattern. + /// The match behaviour. + /// The . + IRequestBuilder WithHeader(string name, string pattern, MatchBehaviour matchBehaviour); + + /// + /// WithHeader: matching based on name, pattern, ignoreCase and matchBehaviour. + /// + /// The name. + /// The pattern. + /// Ignore the case from the pattern. + /// The match behaviour. + /// The . + IRequestBuilder WithHeader(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithHeader: matching based on name, patterns and matchBehaviour. + /// + /// The name. + /// The patterns. + /// The match behaviour. + /// The to use. + /// The . + IRequestBuilder WithHeader(string name, string[] patterns, MatchBehaviour matchBehaviour, MatchOperator matchOperator = MatchOperator.Or); + + /// + /// WithHeader: matching based on name, patterns, ignoreCase and matchBehaviour. + /// + /// The name. + /// The patterns. + /// Ignore the case from the pattern. + /// The match behaviour. + /// The to use. + /// The . + IRequestBuilder WithHeader(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or); + + /// + /// WithHeader: matching based on name and IStringMatcher[]. + /// + /// The name. + /// The matchers. + /// The . + IRequestBuilder WithHeader(string name, params IStringMatcher[] matchers); + + /// + /// WithHeader: matching based on name, ignoreCase and IStringMatcher[]. + /// + /// The name. + /// Ignore the case from the header-keys. + /// The matchers. + /// The . + IRequestBuilder WithHeader(string name, bool ignoreCase, params IStringMatcher[] matchers); + + /// + /// WithHeader: matching based on name, ignoreCase, matchBehaviour and IStringMatcher[]. + /// + /// The name. + /// Ignore the case from the header-keys. + /// The match behaviour. + /// The to use. + /// The matchers. + /// The . + IRequestBuilder WithHeader(string name, bool ignoreCase, MatchBehaviour matchBehaviour, MatchOperator matchOperator = MatchOperator.Or, params IStringMatcher[] matchers); + + /// + /// WithHeader: matching based on functions. + /// + /// The headers funcs. + /// The . + IRequestBuilder WithHeader(params Func, bool>[] funcs); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IHttpVersionBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IHttpVersionBuilder.cs new file mode 100644 index 000000000..f10b1a39a --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IHttpVersionBuilder.cs @@ -0,0 +1,20 @@ +// Copyright © WireMock.Net + +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +/// +/// The HttpVersionBuilder interface. +/// +public interface IHttpVersionBuilder : IRequestMatcher +{ + /// + /// WithHttpVersion + /// + /// The HTTP Version to match. + /// The match behaviour. (default = "AcceptOnMatch") + /// The . + IRequestBuilder WithHttpVersion(string version, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IMethodRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IMethodRequestBuilder.cs new file mode 100644 index 000000000..879b5aeb3 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IMethodRequestBuilder.cs @@ -0,0 +1,96 @@ +// Copyright © WireMock.Net + +using WireMock.Matchers; + +namespace WireMock.RequestBuilders; + +/// +/// The MethodRequestBuilder interface. +/// +public interface IMethodRequestBuilder : IHeadersRequestBuilder +{ + /// + /// UsingConnect: add HTTP Method matching on `CONNECT` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingConnect(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingDelete: add HTTP Method matching on `DELETE` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingDelete(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingGet: add HTTP Method matching on `GET` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingGet(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingHead: Add HTTP Method matching on `HEAD` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingHead(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingPost: add HTTP Method matching on `POST` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingPost(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingPatch: add HTTP Method matching on `PATCH` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingPatch(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingPut: add HTTP Method matching on `OPTIONS` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingOptions(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingPut: add HTTP Method matching on `PUT` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingPut(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingTrace: add HTTP Method matching on `TRACE` and matchBehaviour (optional). + /// + /// The match behaviour. + /// The . + IRequestBuilder UsingTrace(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// UsingAnyMethod: add HTTP Method matching on any method. + /// + /// The . + IRequestBuilder UsingAnyMethod(); + + /// + /// UsingMethod: add HTTP Method matching on any methods and matchBehaviour. + /// + /// The match behaviour. + /// The to use. + /// The method or methods. + /// The . + IRequestBuilder UsingMethod(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params string[] methods); + + /// + /// UsingMethod: add HTTP Method matching on any methods. + /// + /// The method or methods. + /// The . + IRequestBuilder UsingMethod(params string[] methods); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IParamsRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IParamsRequestBuilder.cs new file mode 100644 index 000000000..605060035 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IParamsRequestBuilder.cs @@ -0,0 +1,110 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using WireMock.Matchers; +using WireMock.Types; + +namespace WireMock.RequestBuilders; + +/// +/// The ParamsRequestBuilder interface. +/// +public interface IParamsRequestBuilder : IBodyRequestBuilder +{ + /// + /// WithParam: matching on key only. + /// + /// The key. + /// The match behaviour (optional). + /// The . + IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithParam: matching on key only. + /// + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The match behaviour (optional). + /// The . + IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch); + + /// + /// WithParam: matching on key and values. + /// + /// The key. + /// The values. + /// The . + IRequestBuilder WithParam(string key, params string[] values); + + /// + /// WithParam: matching on key and values. + /// + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The values. + /// The . + IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values); + + /// + /// WithParam: matching on key and matchers. + /// + /// The key. + /// The matchers. + /// The . + IRequestBuilder WithParam(string key, params IStringMatcher[] matchers); + + /// + /// WithParam: matching on key and matchers. + /// + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The matchers. + /// The . + IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers); + + /// + /// WithParam: matching on key, values and matchBehaviour. + /// + /// The key. + /// The values. + /// The match behaviour. + /// The . + IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values); + + /// + /// WithParam: matching on key, values and matchBehaviour. + /// + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The values. + /// The match behaviour. + /// The . + IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values); + + /// + /// WithParam: matching on key, matchers and matchBehaviour. + /// + /// The key. + /// The matchers. + /// The match behaviour. + /// The . + IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers); + + /// + /// WithParam: matching on key, matchers and matchBehaviour. + /// + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The matchers. + /// The match behaviour. + /// The . + IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params IStringMatcher[] matchers); + + /// + /// WithParam: matching on functions. + /// + /// The funcs. + /// The . + IRequestBuilder WithParam(params Func>, bool>[] funcs); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IRequestBuilder.cs new file mode 100644 index 000000000..f2d411e60 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IRequestBuilder.cs @@ -0,0 +1,18 @@ +// Copyright © WireMock.Net + +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +/// +/// IRequestBuilder +/// +public interface IRequestBuilder : IClientIPRequestBuilder +{ + /// + /// The link back to the Mapping. + /// + internal IMapping Mapping { get; set; } + + public IRequestBuilder Add(T requestMatcher) where T : IRequestMatcher; +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IUrlAndPathRequestBuilder.cs b/src/WireMock.Net.Common/RequestBuilders/IUrlAndPathRequestBuilder.cs new file mode 100644 index 000000000..7118e8290 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/IUrlAndPathRequestBuilder.cs @@ -0,0 +1,86 @@ +// Copyright © WireMock.Net + +using System; +using WireMock.Matchers; + +namespace WireMock.RequestBuilders; + +/// +/// IUrlAndPathRequestBuilder +/// +public interface IUrlAndPathRequestBuilder : IMethodRequestBuilder +{ + /// + /// WithPath: add path matching based on IStringMatchers. + /// + /// The matchers. + /// The . + IRequestBuilder WithPath(params IStringMatcher[] matchers); + + /// + /// WithPath: add path matching based on MatchOperator and IStringMatchers. + /// + /// The to use. + /// The matchers. + /// The . + IRequestBuilder WithPath(MatchOperator matchOperator, params IStringMatcher[] matchers); + + /// + /// WithPath: add path matching based on paths. + /// + /// The paths. + /// The . + IRequestBuilder WithPath(params string[] paths); + + /// + /// WithPath: add path matching based on paths , matchBehaviour and MatchOperator. + /// + /// The to use. + /// The paths. + /// The . + IRequestBuilder WithPath(MatchOperator matchOperator, params string[] paths); + + /// + /// WithPath: add path matching based on functions. + /// + /// The path funcs. + /// The . + IRequestBuilder WithPath(params Func[] funcs); + + /// + /// WithUrl: add url matching based on IStringMatcher[]. + /// + /// The matchers. + /// The . + IRequestBuilder WithUrl(params IStringMatcher[] matchers); + + /// + /// WithUrl: add url matching based on MatchOperator and IStringMatchers. + /// + /// The to use. + /// The matchers. + /// The . + IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers); + + /// + /// WithUrl: add url matching based on urls. + /// + /// The urls. + /// The . + IRequestBuilder WithUrl(params string[] urls); + + /// + /// WithUrl: add url matching based on urls. + /// + /// The to use. + /// The urls. + /// The . + IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls); + + /// + /// WithUrl: add url matching based on functions. + /// + /// The url functions. + /// The . + IRequestBuilder WithUrl(params Func[] funcs); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.ClientIP.cs b/src/WireMock.Net.Common/RequestBuilders/Request.ClientIP.cs new file mode 100644 index 000000000..8629c9687 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.ClientIP.cs @@ -0,0 +1,50 @@ +// Copyright © WireMock.Net + +using System; +using Stef.Validation; +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithClientIP(params IStringMatcher[] matchers) + { + return WithClientIP(MatchOperator.Or, matchers); + } + + /// + public IRequestBuilder WithClientIP(MatchOperator matchOperator, params IStringMatcher[] matchers) + { + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageClientIPMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, matchers)); + return this; + } + + /// + public IRequestBuilder WithClientIP(params string[] clientIPs) + { + return WithClientIP(MatchOperator.Or, clientIPs); + } + + /// + public IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] clientIPs) + { + Guard.NotNullOrEmpty(clientIPs); + + _requestMatchers.Add(new RequestMessageClientIPMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, clientIPs)); + return this; + } + + /// + public IRequestBuilder WithClientIP(params Func[] funcs) + { + Guard.NotNullOrEmpty(funcs); + + _requestMatchers.Add(new RequestMessageClientIPMatcher(funcs)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.UsingMethods.cs b/src/WireMock.Net.Common/RequestBuilders/Request.UsingMethods.cs new file mode 100644 index 000000000..c691d41ef --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.UsingMethods.cs @@ -0,0 +1,104 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System.Linq; +using Stef.Validation; +using WireMock.Constants; +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder UsingConnect(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.CONNECT)); + return this; + } + + /// + public IRequestBuilder UsingDelete(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.DELETE)); + return this; + } + + /// + public IRequestBuilder UsingGet(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.GET)); + return this; + } + + /// + public IRequestBuilder UsingHead(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.HEAD)); + return this; + } + + /// + public IRequestBuilder UsingOptions(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.OPTIONS)); + return this; + } + + /// + public IRequestBuilder UsingPost(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.POST)); + return this; + } + + /// + public IRequestBuilder UsingPatch(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.PATCH)); + return this; + } + + /// + public IRequestBuilder UsingPut(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.PUT)); + return this; + } + + /// + public IRequestBuilder UsingTrace(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.TRACE)); + return this; + } + + /// + public IRequestBuilder UsingAnyMethod() + { + var matchers = _requestMatchers.Where(m => m is RequestMessageMethodMatcher).ToList(); + foreach (var matcher in matchers) + { + _requestMatchers.Remove(matcher); + } + + return this; + } + + /// + public IRequestBuilder UsingMethod(params string[] methods) + { + return UsingMethod(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, methods); + } + + /// + public IRequestBuilder UsingMethod(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params string[] methods) + { + Guard.NotNullOrEmpty(methods); + + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, matchOperator, methods)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithBody.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithBody.cs new file mode 100644 index 000000000..9caf04712 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithBody.cs @@ -0,0 +1,100 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System; +using System.Collections.Generic; +using Stef.Validation; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using WireMock.Util; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithBody(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body)); + return this; + } + + /// + public IRequestBuilder WithBody(byte[] body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body)); + return this; + } + + /// + public IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + _requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, body)); + return this; + } + + /// + public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithBody(new IMatcher[] { new JsonMatcher(matchBehaviour, body) }); + } + + /// + public IRequestBuilder WithBody(IMatcher matcher) + { + return WithBody(new[] { matcher }); + } + + /// + public IRequestBuilder WithBody(IMatcher[] matchers, MatchOperator matchOperator = MatchOperator.Or) + { + Guard.NotNull(matchers); + + _requestMatchers.Add(new RequestMessageBodyMatcher(matchOperator, matchers)); + return this; + } + + /// + public IRequestBuilder WithBody(Func func) + { + Guard.NotNull(func); + + _requestMatchers.Add(new RequestMessageBodyMatcher(func)); + return this; + } + + /// + public IRequestBuilder WithBody(Func func) + { + Guard.NotNull(func); + + _requestMatchers.Add(new RequestMessageBodyMatcher(func)); + return this; + } + + /// + public IRequestBuilder WithBody(Func func) + { + Guard.NotNull(func); + + _requestMatchers.Add(new RequestMessageBodyMatcher(func)); + return this; + } + + /// + public IRequestBuilder WithBody(Func func) + { + Guard.NotNull(func); + + _requestMatchers.Add(new RequestMessageBodyMatcher(func)); + return this; + } + + /// + public IRequestBuilder WithBody(Func?, bool> func) + { + _requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func))); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithCookies.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithCookies.cs new file mode 100644 index 000000000..a34eeba0d --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithCookies.cs @@ -0,0 +1,83 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using Stef.Validation; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour) + { + return WithCookie(name, pattern, true, matchBehaviour); + } + + /// + public IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + Guard.NotNull(name); + Guard.NotNull(pattern); + + _requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, pattern, ignoreCase)); + return this; + } + + /// + public IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour) + { + return WithCookie(name, patterns, true, matchBehaviour); + } + + /// + public IRequestBuilder WithCookie(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + Guard.NotNull(name); + Guard.NotNull(patterns); + + _requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, patterns)); + return this; + } + + /// + public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers) + { + Guard.NotNull(name); + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, false, matchers)); + return this; + } + + /// + public IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers) + { + Guard.NotNull(name); + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, ignoreCase, matchers)); + return this; + } + + /// + public IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers) + { + Guard.NotNull(name); + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, matchers)); + return this; + } + + /// + public IRequestBuilder WithCookie(params Func, bool>[] funcs) + { + Guard.NotNullOrEmpty(funcs); + + _requestMatchers.Add(new RequestMessageCookieMatcher(funcs)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithHeaders.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithHeaders.cs new file mode 100644 index 000000000..af1b75eda --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithHeaders.cs @@ -0,0 +1,85 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System; +using System.Collections.Generic; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using Stef.Validation; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithHeader(string name, string pattern, MatchBehaviour matchBehaviour) + { + return WithHeader(name, pattern, true, matchBehaviour); + } + + /// + public IRequestBuilder WithHeader(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + Guard.NotNull(name); + Guard.NotNull(pattern); + + _requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, name, pattern, ignoreCase)); + return this; + } + + /// + public IRequestBuilder WithHeader(string name, string[] patterns, MatchBehaviour matchBehaviour, MatchOperator matchOperator = MatchOperator.Or) + { + return WithHeader(name, patterns, true, matchBehaviour, matchOperator); + } + + /// + public IRequestBuilder WithHeader(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or) + { + Guard.NotNull(name); + Guard.NotNull(patterns); + + _requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, matchOperator, name, ignoreCase, patterns)); + return this; + } + + /// + public IRequestBuilder WithHeader(string name, params IStringMatcher[] matchers) + { + Guard.NotNull(name); + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, name, false, matchers)); + return this; + } + + /// + public IRequestBuilder WithHeader(string name, bool ignoreCase, params IStringMatcher[] matchers) + { + Guard.NotNull(name); + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, name, ignoreCase, matchers)); + return this; + } + + /// + public IRequestBuilder WithHeader(string name, bool ignoreCase, MatchBehaviour matchBehaviour, MatchOperator matchOperator, params IStringMatcher[] matchers) + { + Guard.NotNull(name); + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, matchOperator, name, ignoreCase, matchers)); + return this; + } + + /// + public IRequestBuilder WithHeader(params Func, bool>[] funcs) + { + Guard.NotNullOrEmpty(funcs); + + _requestMatchers.Add(new RequestMessageHeaderMatcher(funcs)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithHttpVersion.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithHttpVersion.cs new file mode 100644 index 000000000..2d0ed702e --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithHttpVersion.cs @@ -0,0 +1,15 @@ +// Copyright © WireMock.Net + +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithHttpVersion(string version, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return Add(new RequestMessageHttpVersionMatcher(matchBehaviour, version)); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithParam.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithParam.cs new file mode 100644 index 000000000..cea69e287 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithParam.cs @@ -0,0 +1,93 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System; +using System.Collections.Generic; +using WireMock.Matchers; +using WireMock.Matchers.Request; +using WireMock.Types; +using Stef.Validation; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + return WithParam(key, false, matchBehaviour); + } + + /// + public IRequestBuilder WithParam(string key, bool ignoreCase, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + Guard.NotNull(key); + + _requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase)); + return this; + } + + /// + public IRequestBuilder WithParam(string key, params string[] values) + { + return WithParam(key, MatchBehaviour.AcceptOnMatch, false, values); + } + + /// + public IRequestBuilder WithParam(string key, bool ignoreCase, params string[] values) + { + return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, values); + } + + /// + public IRequestBuilder WithParam(string key, params IStringMatcher[] matchers) + { + return WithParam(key, MatchBehaviour.AcceptOnMatch, false, matchers); + } + + /// + public IRequestBuilder WithParam(string key, bool ignoreCase, params IStringMatcher[] matchers) + { + return WithParam(key, MatchBehaviour.AcceptOnMatch, ignoreCase, matchers); + } + + /// + public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params string[] values) + { + return WithParam(key, matchBehaviour, false, values); + } + + /// + public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase = false, params string[] values) + { + Guard.NotNull(key); + + _requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, values)); + return this; + } + + /// + public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers) + { + return WithParam(key, matchBehaviour, false, matchers); + } + + /// + public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, bool ignoreCase, params IStringMatcher[] matchers) + { + Guard.NotNull(key); + + _requestMatchers.Add(new RequestMessageParamMatcher(matchBehaviour, key, ignoreCase, matchers)); + return this; + } + + /// + public IRequestBuilder WithParam(params Func>, bool>[] funcs) + { + Guard.NotNullOrEmpty(funcs); + + _requestMatchers.Add(new RequestMessageParamMatcher(funcs)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithPath.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithPath.cs new file mode 100644 index 000000000..2a5939bbb --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithPath.cs @@ -0,0 +1,50 @@ +// Copyright © WireMock.Net + +using System; +using Stef.Validation; +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithPath(params IStringMatcher[] matchers) + { + return WithPath(MatchOperator.Or, matchers); + } + + /// + public IRequestBuilder WithPath(MatchOperator matchOperator, params IStringMatcher[] matchers) + { + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessagePathMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, matchers)); + return this; + } + + /// + public IRequestBuilder WithPath(params string[] paths) + { + return WithPath(MatchOperator.Or, paths); + } + + /// + public IRequestBuilder WithPath(MatchOperator matchOperator, params string[] paths) + { + Guard.NotNullOrEmpty(paths); + + _requestMatchers.Add(new RequestMessagePathMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, paths)); + return this; + } + + /// + public IRequestBuilder WithPath(params Func[] funcs) + { + Guard.NotNullOrEmpty(funcs); + + _requestMatchers.Add(new RequestMessagePathMatcher(funcs)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithUrl.cs b/src/WireMock.Net.Common/RequestBuilders/Request.WithUrl.cs new file mode 100644 index 000000000..239f98f04 --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.WithUrl.cs @@ -0,0 +1,50 @@ +// Copyright © WireMock.Net + +using System; +using Stef.Validation; +using WireMock.Matchers; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +public partial class Request +{ + /// + public IRequestBuilder WithUrl(params IStringMatcher[] matchers) + { + return WithUrl(MatchOperator.Or, matchers); + } + + /// + public IRequestBuilder WithUrl(MatchOperator matchOperator, params IStringMatcher[] matchers) + { + Guard.NotNullOrEmpty(matchers); + + _requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers)); + return this; + } + + /// + public IRequestBuilder WithUrl(params string[] urls) + { + return WithUrl(MatchOperator.Or, urls); + } + + /// + public IRequestBuilder WithUrl(MatchOperator matchOperator, params string[] urls) + { + Guard.NotNullOrEmpty(urls); + + _requestMatchers.Add(new RequestMessageUrlMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, urls)); + return this; + } + + /// + public IRequestBuilder WithUrl(params Func[] funcs) + { + Guard.NotNullOrEmpty(funcs); + + _requestMatchers.Add(new RequestMessageUrlMatcher(funcs)); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.cs b/src/WireMock.Net.Common/RequestBuilders/Request.cs new file mode 100644 index 000000000..0d629da5b --- /dev/null +++ b/src/WireMock.Net.Common/RequestBuilders/Request.cs @@ -0,0 +1,83 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Stef.Validation; +using WireMock.Matchers.Request; + +namespace WireMock.RequestBuilders; + +/// +/// The Request Builder +/// +public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder +{ + private readonly IList _requestMatchers; + + /// + public IMapping Mapping { get; set; } = null!; + + /// + /// Creates this instance. + /// + /// The . + public static IRequestBuilder Create() + { + return new Request(new List()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The request matchers. + private Request(IList requestMatchers) : base(requestMatchers) + { + _requestMatchers = Guard.NotNull(requestMatchers); + } + + /// + /// Gets the request message matchers. + /// + /// Type of IRequestMatcher + /// A List{T} + public IList GetRequestMessageMatchers() where T : IRequestMatcher + { + return new ReadOnlyCollection(_requestMatchers.OfType().ToList()); + } + + /// + /// Gets the request message matcher. + /// + /// Type of IRequestMatcher + /// A RequestMatcher + public T? GetRequestMessageMatcher() where T : IRequestMatcher + { + return _requestMatchers.OfType().FirstOrDefault(); + } + + /// + /// Gets the request message matcher. + /// + /// Type of IRequestMatcher + /// A RequestMatcher + public T? GetRequestMessageMatcher(Func func) where T : IRequestMatcher + { + return _requestMatchers.OfType().FirstOrDefault(func); + } + + /// + public IRequestBuilder Add(T requestMatcher) where T : IRequestMatcher + { + foreach (var existing in _requestMatchers.OfType().ToArray()) + { + _requestMatchers.Remove(existing); + } + + _requestMatchers.Add(requestMatcher); + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Util/ReflectionUtils.cs b/src/WireMock.Net.Common/Util/ReflectionUtils.cs new file mode 100644 index 000000000..f16db2f2d --- /dev/null +++ b/src/WireMock.Net.Common/Util/ReflectionUtils.cs @@ -0,0 +1,50 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; + +namespace WireMock.Util; + +public 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 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); + }); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Util/TypeLoader.cs b/src/WireMock.Net.Common/Util/TypeLoader.cs new file mode 100644 index 000000000..b727268ef --- /dev/null +++ b/src/WireMock.Net.Common/Util/TypeLoader.cs @@ -0,0 +1,95 @@ +// 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; + +public static class TypeLoader +{ + private static readonly ConcurrentDictionary FoundTypes = new(); + + public static bool TryFindType([NotNullWhen(true)] out Type? pluginType) where TInterface : class + { + var key = typeof(TInterface).FullName!; + + pluginType = FoundTypes.GetOrAdd(key, _ => TryFindTypeInDlls(null, out var foundType) ? foundType : null); + + return pluginType != null; + } + + public static bool TryFindType(string implementationTypeFullName, [NotNullWhen(true)] out Type? pluginType) where TInterface : class + { + var @interface = typeof(TInterface).FullName; + var key = $"{@interface}_{implementationTypeFullName}"; + + pluginType = FoundTypes.GetOrAdd(key, _ => TryFindTypeInDlls(implementationTypeFullName, out var foundType) ? foundType : null); + + return pluginType != null; + } + + public static TInterface Load(params object?[] args) where TInterface : class + { + if (TryFindType(out var pluginType)) + { + return (TInterface)Activator.CreateInstance(pluginType, args)!; + } + + throw new DllNotFoundException($"No dll found which implements Interface '{typeof(TInterface).FullName}'."); + } + + public static TInterface LoadByFullName(string implementationTypeFullName, params object?[] args) where TInterface : class + { + Guard.NotNullOrEmpty(implementationTypeFullName); + + if (TryFindType(implementationTypeFullName, out var pluginType)) + { + return (TInterface)Activator.CreateInstance(pluginType, args)!; + } + + throw new DllNotFoundException($"No dll found which implements Interface '{typeof(TInterface).FullName}' and has FullName '{implementationTypeFullName}'."); + } + + private static bool TryFindTypeInDlls(string? implementationTypeFullName, [NotNullWhen(true)] out Type? pluginType) where TInterface : class + { + foreach (var file in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll")) + { + try + { + var assembly = Assembly.Load(new AssemblyName + { + Name = Path.GetFileNameWithoutExtension(file) + }); + + if (TryGetImplementationTypeByInterfaceAndOptionalFullName(assembly, implementationTypeFullName, out pluginType)) + { + return true; + } + } + catch + { + // no-op: just try next .dll + } + } + + pluginType = null; + return false; + } + + private static bool TryGetImplementationTypeByInterfaceAndOptionalFullName(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; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/WireMock.Net.Common.csproj b/src/WireMock.Net.Common/WireMock.Net.Common.csproj new file mode 100644 index 000000000..6663da67d --- /dev/null +++ b/src/WireMock.Net.Common/WireMock.Net.Common.csproj @@ -0,0 +1,100 @@ + + + + Common classes for WireMock.Net + WireMock.Net.Common + Stef Heyenrath + net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0 + true + wiremock;common + WireMock + {B6269AAC-170A-4346-8B9B-123DED3D9A45} + true + true + true + true + ../WireMock.Net/WireMock.Net.ruleset + true + ../WireMock.Net/WireMock.Net.snk + + true + MIT + + + + true + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + diff --git a/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs b/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs index 247aa8121..96668d170 100644 --- a/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs +++ b/src/WireMock.Net.GraphQL/Matchers/GraphQLMatcher.cs @@ -1,6 +1,6 @@ // Copyright © WireMock.Net -#if GRAPHQL +// #if GRAPHQL using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -202,4 +202,4 @@ private ISchema BuildSchema(string typeDefinitions) return schema; } } -#endif \ No newline at end of file +//#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs b/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs index a600cebd6..75bd17dbb 100644 --- a/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs +++ b/src/WireMock.Net.GraphQL/Matchers/Models/WireMockCustomScalarGraphType.cs @@ -1,6 +1,6 @@ // Copyright © WireMock.Net -#if GRAPHQL +//#if GRAPHQL using System; using GraphQL.Types; @@ -29,4 +29,4 @@ public abstract class WireMockCustomScalarGraphType : ScalarGraphType return (T)Convert.ChangeType(value, typeof(T)); } } -#endif \ No newline at end of file +//#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs b/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs index 2ab03d0d9..bfaa54133 100644 --- a/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs +++ b/src/WireMock.Net.GraphQL/Matchers/Request/RequestMessageGraphQLMatcher.cs @@ -1,6 +1,6 @@ // Copyright © WireMock.Net -#if GRAPHQL +// #if GRAPHQL using System; using System.Collections.Generic; using System.Linq; @@ -93,4 +93,4 @@ private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, AnyO return new[] { TypeLoader.Load(schema, customScalars, matchBehaviour, MatchOperator.Or) }.Cast().ToArray(); } } -#endif \ No newline at end of file +//#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs b/src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs index 6d302c658..d24a6a74b 100644 --- a/src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs +++ b/src/WireMock.Net.GraphQL/RequestBuilders/IGraphQLRequestBuilderExtensions.cs @@ -1,6 +1,6 @@ // Copyright © WireMock.Net -#if GRAPHQL +// #if GRAPHQL // ReSharper disable InconsistentNaming using System; using System.Collections.Generic; @@ -127,4 +127,4 @@ public static IRequestBuilder WithBodyAsGraphQLSchema(this IRequestBuilder reque return WithGraphQLSchema(requestBuilder, body, matchBehaviour); } } -#endif \ No newline at end of file +//#endif \ No newline at end of file diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj index 5a52a1d79..fa72110fd 100644 --- a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -26,12 +26,21 @@
- - - + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive +
\ No newline at end of file diff --git a/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj b/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj index 53e126654..3f2f0891b 100644 --- a/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj +++ b/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj @@ -26,8 +26,6 @@
- - diff --git a/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj b/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj index 67e99b964..d1cbca6dc 100644 --- a/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj +++ b/src/WireMock.Net.ProtoBuf/WireMock.Net.ProtoBuf.csproj @@ -27,8 +27,6 @@
- - From de3c449b5c4ea1400dc84ec83baa58142b3b090f Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 27 Jul 2024 18:33:30 +0200 Subject: [PATCH 20/20] ? --- WireMock.Net Solution.sln | 2 +- .../WireMock.Net.GraphQL.csproj | 2 +- .../Compatibility/EmptyArray.cs | 13 + .../Compatibility/StringExtensions.cs | 17 + .../Exceptions/WireMockException.cs | 0 .../Extensions/AnyOfExtensions.cs | 0 .../Extensions/ExceptionExtensions.cs | 0 .../IMapping.cs | 21 +- .../Matchers/ExactMatcher.cs | 93 +++++ .../Matchers/ExactObjectMatcher.cs | 76 ++++ .../Helpers/BodyDataMatchScoreCalculator.cs | 71 ++++ .../Matchers/IGraphQLMatcher.cs | 0 .../Matchers/IIgnoreCaseMatcher.cs | 15 + .../Matchers/IMatcher.cs | 0 .../Matchers/IObjectMatcher.cs | 22 ++ .../Matchers/IStringMatcher.cs | 0 .../Matchers/MatchBehaviour.cs | 0 .../Matchers/MatchBehaviourHelper.cs | 0 .../Matchers/MatchOperator.cs | 0 .../Matchers/MatchResult.cs | 0 .../Matchers/MatchScores.cs | 0 .../Matchers/NotNullOrEmptyMatcher.cs | 74 ++++ .../Matchers/RegexMatcher.cs | 128 +++++++ .../Matchers/Request/CompositeMatcherType.cs | 19 + .../Request/IRequestMessageGraphQLMatcher.cs | 0 .../Matchers/Request/RequestMatchResult.cs | 58 +++ .../Request/RequestMessageBodyMatcher.cs | 189 ++++++++++ .../Request/RequestMessageClientIPMatcher.cs | 100 ++++++ .../Request/RequestMessageCompositeMatcher.cs | 50 +++ .../Request/RequestMessageCookieMatcher.cs | 130 +++++++ .../Request/RequestMessageHeaderMatcher.cs | 152 ++++++++ .../RequestMessageHttpVersionMatcher.cs | 88 +++++ .../Request/RequestMessageMethodMatcher.cs | 49 +++ .../Request/RequestMessageParamMatcher.cs | 147 ++++++++ .../RequestMessageScenarioAndStateMatcher.cs | 42 +++ .../Request/RequestMessageUrlMatcher.cs | 100 ++++++ .../Matchers/WildcardMatcher.cs | 84 +++++ .../Models/GraphQLSchemaDetails.cs | 0 .../Models/StringPattern.cs | 0 .../RegularExpressions/RegexExtended.cs | 91 +++++ .../RequestBuilders/IBodyRequestBuilder.cs | 0 .../IClientIPRequestBuilder.cs | 0 .../RequestBuilders/ICookiesRequestBuilder.cs | 0 .../RequestBuilders/IHeadersRequestBuilder.cs | 0 .../RequestBuilders/IHttpVersionBuilder.cs | 0 .../RequestBuilders/IMethodRequestBuilder.cs | 0 .../RequestBuilders/IParamsRequestBuilder.cs | 0 .../RequestBuilders/IRequestBuilder.cs | 0 .../IUrlAndPathRequestBuilder.cs | 0 .../RequestBuilders/Request.ClientIP.cs | 0 .../RequestBuilders/Request.UsingMethods.cs | 0 .../RequestBuilders/Request.WithBody.cs | 0 .../RequestBuilders/Request.WithCookies.cs | 0 .../RequestBuilders/Request.WithHeaders.cs | 0 .../Request.WithHttpVersion.cs | 0 .../RequestBuilders/Request.WithParam.cs | 0 .../RequestBuilders/Request.WithPath.cs | 0 .../RequestBuilders/Request.WithUrl.cs | 0 .../RequestBuilders/Request.cs | 0 src/WireMock.Net.Shared/RequestMessage.cs | 208 +++++++++++ .../ResponseProviders/IResponseProvider.cs | 23 ++ .../Settings/HttpClientSettings.cs | 32 ++ .../Settings/ProxyAndRecordSettings.cs | 115 ++++++ .../Settings/ProxySaveMappingSetting.cs | 50 +++ .../Settings/ProxySaveMappingSettings.cs | 24 ++ .../Settings/ProxyUrlReplaceSettings.cs | 24 ++ .../Settings/WebProxySettings.cs | 29 ++ .../Settings/WebhookSettings.cs | 10 + .../Settings/WireMockCertificateSettings.cs | 55 +++ .../Settings/WireMockServerSettings.cs | 331 ++++++++++++++++++ .../Util/ReflectionUtils.cs | 0 .../Util/TypeLoader.cs | 0 .../WireMock.Net.Shared.csproj} | 68 ++-- 73 files changed, 2751 insertions(+), 51 deletions(-) create mode 100644 src/WireMock.Net.Shared/Compatibility/EmptyArray.cs create mode 100644 src/WireMock.Net.Shared/Compatibility/StringExtensions.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Exceptions/WireMockException.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Extensions/AnyOfExtensions.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Extensions/ExceptionExtensions.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/IMapping.cs (88%) create mode 100644 src/WireMock.Net.Shared/Matchers/ExactMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/ExactObjectMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Helpers/BodyDataMatchScoreCalculator.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/IGraphQLMatcher.cs (100%) create mode 100644 src/WireMock.Net.Shared/Matchers/IIgnoreCaseMatcher.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/IMatcher.cs (100%) create mode 100644 src/WireMock.Net.Shared/Matchers/IObjectMatcher.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/IStringMatcher.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/MatchBehaviour.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/MatchBehaviourHelper.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/MatchOperator.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/MatchResult.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/MatchScores.cs (100%) create mode 100644 src/WireMock.Net.Shared/Matchers/NotNullOrEmptyMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/RegexMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/CompositeMatcherType.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Matchers/Request/IRequestMessageGraphQLMatcher.cs (100%) create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMatchResult.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageBodyMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageClientIPMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageCompositeMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageCookieMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageHeaderMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageHttpVersionMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageMethodMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageParamMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/Request/RequestMessageUrlMatcher.cs create mode 100644 src/WireMock.Net.Shared/Matchers/WildcardMatcher.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Models/GraphQLSchemaDetails.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Models/StringPattern.cs (100%) create mode 100644 src/WireMock.Net.Shared/RegularExpressions/RegexExtended.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IBodyRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IClientIPRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/ICookiesRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IHeadersRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IHttpVersionBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IMethodRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IParamsRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/IUrlAndPathRequestBuilder.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.ClientIP.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.UsingMethods.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithBody.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithCookies.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithHeaders.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithHttpVersion.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithParam.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithPath.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.WithUrl.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/RequestBuilders/Request.cs (100%) create mode 100644 src/WireMock.Net.Shared/RequestMessage.cs create mode 100644 src/WireMock.Net.Shared/ResponseProviders/IResponseProvider.cs create mode 100644 src/WireMock.Net.Shared/Settings/HttpClientSettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/ProxyAndRecordSettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/ProxySaveMappingSetting.cs create mode 100644 src/WireMock.Net.Shared/Settings/ProxySaveMappingSettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/ProxyUrlReplaceSettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/WebProxySettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/WebhookSettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/WireMockCertificateSettings.cs create mode 100644 src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Util/ReflectionUtils.cs (100%) rename src/{WireMock.Net.Common => WireMock.Net.Shared}/Util/TypeLoader.cs (100%) rename src/{WireMock.Net.Common/WireMock.Net.Common.csproj => WireMock.Net.Shared/WireMock.Net.Shared.csproj} (63%) diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index fd71d1029..1bb99ac01 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -121,7 +121,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.ProtoBuf", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Minimal", "src\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj", "{A39C689E-B94B-4BBB-A270-B5A4C2B6D179}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Common", "src\WireMock.Net.Common\WireMock.Net.Common.csproj", "{CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Shared", "src\WireMock.Net.Shared\WireMock.Net.Shared.csproj", "{CFE2A17D-53FF-42B8-B27E-D0FB3ACC3589}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj index fa72110fd..cdb062046 100644 --- a/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj +++ b/src/WireMock.Net.GraphQL/WireMock.Net.GraphQL.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/WireMock.Net.Shared/Compatibility/EmptyArray.cs b/src/WireMock.Net.Shared/Compatibility/EmptyArray.cs new file mode 100644 index 000000000..84023a609 --- /dev/null +++ b/src/WireMock.Net.Shared/Compatibility/EmptyArray.cs @@ -0,0 +1,13 @@ +// Copyright © WireMock.Net + +// ReSharper disable once CheckNamespace +namespace System; + +public static class EmptyArray +{ +#if NET451 || NET452 + public static readonly T[] Value = new T[0]; +#else + public static readonly T[] Value = Array.Empty(); +#endif +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Compatibility/StringExtensions.cs b/src/WireMock.Net.Shared/Compatibility/StringExtensions.cs new file mode 100644 index 000000000..ddec0476f --- /dev/null +++ b/src/WireMock.Net.Shared/Compatibility/StringExtensions.cs @@ -0,0 +1,17 @@ +// Copyright © WireMock.Net + +#if NET451 || NET452 || NET46 || NET451 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0 +using System.Text.RegularExpressions; + +// ReSharper disable once CheckNamespace +namespace System; + +public static class StringExtensions +{ + public static string Replace(this string text, string oldValue, string newValue, StringComparison stringComparison) + { + var options = stringComparison == StringComparison.OrdinalIgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None; + return Regex.Replace(text, oldValue, newValue, options); + } +} +#endif \ No newline at end of file diff --git a/src/WireMock.Net.Common/Exceptions/WireMockException.cs b/src/WireMock.Net.Shared/Exceptions/WireMockException.cs similarity index 100% rename from src/WireMock.Net.Common/Exceptions/WireMockException.cs rename to src/WireMock.Net.Shared/Exceptions/WireMockException.cs diff --git a/src/WireMock.Net.Common/Extensions/AnyOfExtensions.cs b/src/WireMock.Net.Shared/Extensions/AnyOfExtensions.cs similarity index 100% rename from src/WireMock.Net.Common/Extensions/AnyOfExtensions.cs rename to src/WireMock.Net.Shared/Extensions/AnyOfExtensions.cs diff --git a/src/WireMock.Net.Common/Extensions/ExceptionExtensions.cs b/src/WireMock.Net.Shared/Extensions/ExceptionExtensions.cs similarity index 100% rename from src/WireMock.Net.Common/Extensions/ExceptionExtensions.cs rename to src/WireMock.Net.Shared/Extensions/ExceptionExtensions.cs diff --git a/src/WireMock.Net.Common/IMapping.cs b/src/WireMock.Net.Shared/IMapping.cs similarity index 88% rename from src/WireMock.Net.Common/IMapping.cs rename to src/WireMock.Net.Shared/IMapping.cs index 671029989..91790fc19 100644 --- a/src/WireMock.Net.Common/IMapping.cs +++ b/src/WireMock.Net.Shared/IMapping.cs @@ -178,23 +178,4 @@ public interface IMapping /// The proto definition as text. /// The . IMapping WithProtoDefinition(IdOrText protoDefinition); -} - -/* - executionConditionState">State in which the current mapping can occur. [Optional] - nextState">The next state which will occur after the current mapping execution. [Optional] - stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional] - webhooks">The Webhooks. [Optional] - useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional] - timeSettings">The TimeSettings. [Optional] - data">The data object. [Optional] - - - string? executionConditionState, - string? nextState, - int? stateTimes, - IWebhook[]? webhooks, - bool? useWebhooksFireAndForget, - ITimeSettings? timeSettings, - object? data, -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/ExactMatcher.cs b/src/WireMock.Net.Shared/Matchers/ExactMatcher.cs new file mode 100644 index 000000000..32b556ded --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/ExactMatcher.cs @@ -0,0 +1,93 @@ +// Copyright © WireMock.Net + +using System; +using System.Linq; +using AnyOfTypes; +using Stef.Validation; +using WireMock.Models; + +namespace WireMock.Matchers; + +/// +/// ExactMatcher +/// +/// and +public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher +{ + private readonly AnyOf[] _values; + + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The string value. + public ExactMatcher(MatchBehaviour matchBehaviour, string value) : this(matchBehaviour, true, MatchOperator.Or, new AnyOf(value)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The values. + public ExactMatcher(params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, values) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Ignore the case from the pattern(s). + /// The values. + public ExactMatcher(bool ignoreCase, params AnyOf[] values) : this(MatchBehaviour.AcceptOnMatch, ignoreCase, MatchOperator.Or, values) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// Ignore the case from the pattern(s). + /// The to use. (default = "Or") + /// The values. + public ExactMatcher( + MatchBehaviour matchBehaviour, + bool ignoreCase = false, + MatchOperator matchOperator = MatchOperator.Or, + params AnyOf[] values) + { + _values = Guard.NotNull(values); + + MatchBehaviour = matchBehaviour; + IgnoreCase = ignoreCase; + MatchOperator = matchOperator; + } + + /// + public MatchResult IsMatch(string? input) + { + Func equals = IgnoreCase + ? pattern => string.Equals(pattern, input, StringComparison.OrdinalIgnoreCase) + : pattern => pattern == input; + + var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator); + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score)); + } + + /// + public AnyOf[] GetPatterns() + { + return _values; + } + + /// + public MatchOperator MatchOperator { get; } + + /// + public string Name => "ExactMatcher"; + + /// + public bool IgnoreCase { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/ExactObjectMatcher.cs b/src/WireMock.Net.Shared/Matchers/ExactObjectMatcher.cs new file mode 100644 index 000000000..32814c7f2 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/ExactObjectMatcher.cs @@ -0,0 +1,76 @@ +// Copyright © WireMock.Net + +using System.Linq; +using Stef.Validation; + +namespace WireMock.Matchers; + +/// +/// ExactObjectMatcher +/// +/// +public class ExactObjectMatcher : IObjectMatcher +{ + /// + public object Value { get; } + + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The value. + public ExactObjectMatcher(object value) : this(MatchBehaviour.AcceptOnMatch, value) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The value. + public ExactObjectMatcher(MatchBehaviour matchBehaviour, object value) + { + Value = Guard.NotNull(value); + MatchBehaviour = matchBehaviour; + } + + /// + /// Initializes a new instance of the class. + /// + /// The value. + public ExactObjectMatcher(byte[] value) : this(MatchBehaviour.AcceptOnMatch, value) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The value. + public ExactObjectMatcher(MatchBehaviour matchBehaviour, byte[] value) + { + Value = Guard.NotNull(value); + MatchBehaviour = matchBehaviour; + } + + /// + public MatchResult IsMatch(object? input) + { + bool equals; + if (Value is byte[] valueAsBytes && input is byte[] inputAsBytes) + { + equals = valueAsBytes.SequenceEqual(inputAsBytes); + } + else + { + equals = Equals(Value, input); + } + + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(equals)); + } + + /// + public string Name => "ExactObjectMatcher"; +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Helpers/BodyDataMatchScoreCalculator.cs b/src/WireMock.Net.Shared/Matchers/Helpers/BodyDataMatchScoreCalculator.cs new file mode 100644 index 000000000..bd660cf6a --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Helpers/BodyDataMatchScoreCalculator.cs @@ -0,0 +1,71 @@ +// Copyright © WireMock.Net + +using Stef.Validation; +using WireMock.Types; +using WireMock.Util; + +namespace WireMock.Matchers.Helpers; + +internal static class BodyDataMatchScoreCalculator +{ + public static MatchResult CalculateMatchScore(IBodyData? requestMessage, IMatcher matcher) + { + Guard.NotNull(matcher); + + if (requestMessage == null) + { + return default; + } + + if (matcher is NotNullOrEmptyMatcher notNullOrEmptyMatcher) + { + switch (requestMessage.DetectedBodyType) + { + case BodyType.Json: + case BodyType.String: + case BodyType.FormUrlEncoded: + return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyAsString); + + case BodyType.Bytes: + return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyAsBytes); + + default: + return default; + } + } + + if (matcher is ExactObjectMatcher exactObjectMatcher) + { + // If the body is a byte array, try to match. + var detectedBodyType = requestMessage.DetectedBodyType; + if (detectedBodyType is BodyType.Bytes or BodyType.String or BodyType.FormUrlEncoded) + { + return exactObjectMatcher.IsMatch(requestMessage.BodyAsBytes); + } + } + + // Check if the matcher is a IObjectMatcher + if (matcher is IObjectMatcher objectMatcher) + { + // If the body is a JSON object, try to match. + if (requestMessage.DetectedBodyType == BodyType.Json) + { + return objectMatcher.IsMatch(requestMessage.BodyAsJson); + } + + // If the body is a byte array, try to match. + if (requestMessage.DetectedBodyType == BodyType.Bytes) + { + return objectMatcher.IsMatch(requestMessage.BodyAsBytes); + } + } + + // In case the matcher is a IStringMatcher and If body is a Json or a String, use the BodyAsString to match on. + if (matcher is IStringMatcher stringMatcher && requestMessage.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded) + { + return stringMatcher.IsMatch(requestMessage.BodyAsString); + } + + return default; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/IGraphQLMatcher.cs b/src/WireMock.Net.Shared/Matchers/IGraphQLMatcher.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/IGraphQLMatcher.cs rename to src/WireMock.Net.Shared/Matchers/IGraphQLMatcher.cs diff --git a/src/WireMock.Net.Shared/Matchers/IIgnoreCaseMatcher.cs b/src/WireMock.Net.Shared/Matchers/IIgnoreCaseMatcher.cs new file mode 100644 index 000000000..60bba30b3 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/IIgnoreCaseMatcher.cs @@ -0,0 +1,15 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers; + +/// +/// IIgnoreCaseMatcher +/// +/// +public interface IIgnoreCaseMatcher : IMatcher +{ + /// + /// Ignore the case from the pattern. + /// + bool IgnoreCase { get; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/IMatcher.cs b/src/WireMock.Net.Shared/Matchers/IMatcher.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/IMatcher.cs rename to src/WireMock.Net.Shared/Matchers/IMatcher.cs diff --git a/src/WireMock.Net.Shared/Matchers/IObjectMatcher.cs b/src/WireMock.Net.Shared/Matchers/IObjectMatcher.cs new file mode 100644 index 000000000..59b8d8a3a --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/IObjectMatcher.cs @@ -0,0 +1,22 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers; + +/// +/// IObjectMatcher +/// +public interface IObjectMatcher : IMatcher +{ + /// + /// Gets the value (can be a string or an object). + /// + /// Value + object Value { get; } + + /// + /// Determines whether the specified input is match. + /// + /// The input. + /// MatchResult + MatchResult IsMatch(object? input); +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/IStringMatcher.cs b/src/WireMock.Net.Shared/Matchers/IStringMatcher.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/IStringMatcher.cs rename to src/WireMock.Net.Shared/Matchers/IStringMatcher.cs diff --git a/src/WireMock.Net.Common/Matchers/MatchBehaviour.cs b/src/WireMock.Net.Shared/Matchers/MatchBehaviour.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/MatchBehaviour.cs rename to src/WireMock.Net.Shared/Matchers/MatchBehaviour.cs diff --git a/src/WireMock.Net.Common/Matchers/MatchBehaviourHelper.cs b/src/WireMock.Net.Shared/Matchers/MatchBehaviourHelper.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/MatchBehaviourHelper.cs rename to src/WireMock.Net.Shared/Matchers/MatchBehaviourHelper.cs diff --git a/src/WireMock.Net.Common/Matchers/MatchOperator.cs b/src/WireMock.Net.Shared/Matchers/MatchOperator.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/MatchOperator.cs rename to src/WireMock.Net.Shared/Matchers/MatchOperator.cs diff --git a/src/WireMock.Net.Common/Matchers/MatchResult.cs b/src/WireMock.Net.Shared/Matchers/MatchResult.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/MatchResult.cs rename to src/WireMock.Net.Shared/Matchers/MatchResult.cs diff --git a/src/WireMock.Net.Common/Matchers/MatchScores.cs b/src/WireMock.Net.Shared/Matchers/MatchScores.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/MatchScores.cs rename to src/WireMock.Net.Shared/Matchers/MatchScores.cs diff --git a/src/WireMock.Net.Shared/Matchers/NotNullOrEmptyMatcher.cs b/src/WireMock.Net.Shared/Matchers/NotNullOrEmptyMatcher.cs new file mode 100644 index 000000000..51f022102 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/NotNullOrEmptyMatcher.cs @@ -0,0 +1,74 @@ +// Copyright © WireMock.Net + +using System; +using System.Linq; +using AnyOfTypes; +using WireMock.Models; + +namespace WireMock.Matchers; + +/// +/// NotNullOrEmptyMatcher +/// +/// +public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher +{ + /// + public string Name => nameof(NotNullOrEmptyMatcher); + + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + public object Value { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + public NotNullOrEmptyMatcher(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + MatchBehaviour = matchBehaviour; + Value = string.Empty; + } + + /// + public MatchResult IsMatch(object? input) + { + bool match; + + switch (input) + { + case string @string: + match = !string.IsNullOrEmpty(@string); + break; + + case byte[] bytes: + match = bytes.Any(); + break; + + default: + match = input != null; + break; + } + + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); + } + + /// + public MatchResult IsMatch(string? input) + { + var match = !string.IsNullOrEmpty(input); + + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match)); + } + + /// + public AnyOf[] GetPatterns() + { + return EmptyArray>.Value; + } + + /// + public MatchOperator MatchOperator { get; } = MatchOperator.Or; +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/RegexMatcher.cs b/src/WireMock.Net.Shared/Matchers/RegexMatcher.cs new file mode 100644 index 000000000..89a4f34b5 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/RegexMatcher.cs @@ -0,0 +1,128 @@ +// Copyright © WireMock.Net + +using System; +using System.Linq; +using System.Text.RegularExpressions; +using AnyOfTypes; +using JetBrains.Annotations; +using WireMock.Extensions; +using WireMock.Models; +using WireMock.RegularExpressions; +using Stef.Validation; + +namespace WireMock.Matchers; + +/// +/// Regular Expression Matcher +/// +/// +/// +public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher +{ + private readonly AnyOf[] _patterns; + private readonly Regex[] _expressions; + + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The pattern. + /// Ignore the case from the pattern. + /// Use RegexExtended (default = true). + /// The to use. (default = "Or") + public RegexMatcher( + [RegexPattern] AnyOf pattern, + bool ignoreCase = false, + bool useRegexExtended = true, + MatchOperator matchOperator = MatchOperator.Or) : + this(MatchBehaviour.AcceptOnMatch, new[] { pattern }, ignoreCase, useRegexExtended, matchOperator) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The pattern. + /// Ignore the case from the pattern. + /// Use RegexExtended (default = true). + /// The to use. (default = "Or") + public RegexMatcher( + MatchBehaviour matchBehaviour, + [RegexPattern] AnyOf pattern, + bool ignoreCase = false, + bool useRegexExtended = true, + MatchOperator matchOperator = MatchOperator.Or) : + this(matchBehaviour, new[] { pattern }, ignoreCase, useRegexExtended, matchOperator) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The patterns. + /// Ignore the case from the pattern. + /// Use RegexExtended (default = true). + /// The to use. (default = "Or") + public RegexMatcher( + MatchBehaviour matchBehaviour, + [RegexPattern] AnyOf[] patterns, + bool ignoreCase = false, + bool useRegexExtended = true, + MatchOperator matchOperator = MatchOperator.Or) + { + _patterns = Guard.NotNull(patterns); + IgnoreCase = ignoreCase; + MatchBehaviour = matchBehaviour; + MatchOperator = matchOperator; + + RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline; + + if (ignoreCase) + { + options |= RegexOptions.IgnoreCase; + } + + _expressions = patterns.Select(p => useRegexExtended ? new RegexExtended(p.GetPattern(), options) : new Regex(p.GetPattern(), options)).ToArray(); + } + + /// + public virtual MatchResult IsMatch(string? input) + { + var score = MatchScores.Mismatch; + Exception? exception = null; + + if (input != null) + { + try + { + score = MatchScores.ToScore(_expressions.Select(e => e.IsMatch(input)).ToArray(), MatchOperator); + } + catch (Exception ex) + { + exception = ex; + } + } + + return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception); + } + + /// + public virtual AnyOf[] GetPatterns() + { + return _patterns; + } + + /// + public virtual string Name => nameof(RegexMatcher); + + /// + public bool IgnoreCase { get; } + + /// + public MatchOperator MatchOperator { get; } + +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/CompositeMatcherType.cs b/src/WireMock.Net.Shared/Matchers/Request/CompositeMatcherType.cs new file mode 100644 index 000000000..3a94e932a --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/CompositeMatcherType.cs @@ -0,0 +1,19 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers.Request; + +/// +/// CompositeMatcherType +/// +public enum CompositeMatcherType +{ + /// + /// And + /// + And = 0, + + /// + /// Or + /// + Or = 1 +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Matchers/Request/IRequestMessageGraphQLMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/IRequestMessageGraphQLMatcher.cs similarity index 100% rename from src/WireMock.Net.Common/Matchers/Request/IRequestMessageGraphQLMatcher.cs rename to src/WireMock.Net.Shared/Matchers/Request/IRequestMessageGraphQLMatcher.cs diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMatchResult.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMatchResult.cs new file mode 100644 index 000000000..8342853fe --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMatchResult.cs @@ -0,0 +1,58 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WireMock.Matchers.Request; + +/// +/// RequestMatchResult +/// +public class RequestMatchResult : IRequestMatchResult +{ + /// + public double TotalScore => MatchDetails.Sum(md => md.Score); + + /// + public int TotalNumber => MatchDetails.Count; + + /// + public bool IsPerfectMatch => Math.Abs(TotalScore - TotalNumber) < MatchScores.Tolerance; + + /// + public double AverageTotalScore => TotalNumber == 0 ? MatchScores.Mismatch : TotalScore / TotalNumber; + + /// + public IList MatchDetails { get; } = new List(); + + /// + public double AddScore(Type matcherType, double score, Exception? exception) + { + MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score, Exception = exception }); + + return score; + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. + /// + /// An object to compare with this instance. + /// + /// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes in the sort order. Zero This instance occurs in the same position in the sort order as . Greater than zero This instance follows in the sort order. + /// + public int CompareTo(object? obj) + { + if (obj == null) + { + return -1; + } + + var compareObj = (RequestMatchResult)obj; + + var averageTotalScoreResult = compareObj.AverageTotalScore.CompareTo(AverageTotalScore); + + // In case the score is equal, prefer the one with the most matchers. + return averageTotalScoreResult == 0 ? compareObj.TotalNumber.CompareTo(TotalNumber) : averageTotalScoreResult; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageBodyMatcher.cs new file mode 100644 index 000000000..e05ddf942 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageBodyMatcher.cs @@ -0,0 +1,189 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using Stef.Validation; +using WireMock.Matchers.Helpers; +using WireMock.Util; + +namespace WireMock.Matchers.Request; + +/// +/// The request body matcher. +/// +public class RequestMessageBodyMatcher : IRequestMatcher +{ + /// + /// The body function + /// + public Func? Func { get; } + + /// + /// The body data function for byte[] + /// + public Func? DataFunc { get; } + + /// + /// The body data function for json + /// + public Func? JsonFunc { get; } + + /// + /// The body data function for BodyData + /// + public Func? BodyDataFunc { get; } + + /// + /// The body data function for FormUrlEncoded + /// + public Func?, bool>? FormUrlEncodedFunc { get; } + + /// + /// The matchers. + /// + public IMatcher[]? Matchers { get; } + + /// + /// The + /// + public MatchOperator MatchOperator { get; } = MatchOperator.Or; + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The body. + public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, string body) : + this(new[] { new WildcardMatcher(matchBehaviour, body) }.Cast().ToArray()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The body. + public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, byte[] body) : + this(new[] { new ExactObjectMatcher(matchBehaviour, body) }.Cast().ToArray()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The body. + public RequestMessageBodyMatcher(MatchBehaviour matchBehaviour, object body) : + this(new[] { new ExactObjectMatcher(matchBehaviour, body) }.Cast().ToArray()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The function. + public RequestMessageBodyMatcher(Func func) + { + Func = Guard.NotNull(func); + } + + /// + /// Initializes a new instance of the class. + /// + /// The function. + public RequestMessageBodyMatcher(Func func) + { + DataFunc = Guard.NotNull(func); + } + + /// + /// Initializes a new instance of the class. + /// + /// The function. + public RequestMessageBodyMatcher(Func func) + { + JsonFunc = Guard.NotNull(func); + } + + /// + /// Initializes a new instance of the class. + /// + /// The function. + public RequestMessageBodyMatcher(Func func) + { + BodyDataFunc = Guard.NotNull(func); + } + + /// + /// Initializes a new instance of the class. + /// + /// The function. + public RequestMessageBodyMatcher(Func?, bool> func) + { + FormUrlEncodedFunc = Guard.NotNull(func); + } + + /// + /// Initializes a new instance of the class. + /// + /// The matchers. + public RequestMessageBodyMatcher(params IMatcher[] matchers) + { + Matchers = Guard.NotNull(matchers); + } + + /// + /// Initializes a new instance of the class. + /// + /// The matchers. + /// The to use. + public RequestMessageBodyMatcher(MatchOperator matchOperator, params IMatcher[] matchers) + { + Matchers = Guard.NotNull(matchers); + MatchOperator = matchOperator; + } + + /// + public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) + { + var (score, exception) = CalculateMatchScore(requestMessage).Expand(); + return requestMatchResult.AddScore(GetType(), score, exception); + } + + private MatchResult CalculateMatchScore(IRequestMessage requestMessage) + { + if (Matchers != null && Matchers.Any()) + { + var results = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray(); + return MatchResult.From(results, MatchOperator); + } + + if (Func != null) + { + return MatchScores.ToScore(Func(requestMessage.BodyData?.BodyAsString)); + } + + if (FormUrlEncodedFunc != null) + { + return MatchScores.ToScore(FormUrlEncodedFunc(requestMessage.BodyData?.BodyAsFormUrlEncoded)); + } + + if (JsonFunc != null) + { + return MatchScores.ToScore(JsonFunc(requestMessage.BodyData?.BodyAsJson)); + } + + if (DataFunc != null) + { + return MatchScores.ToScore(DataFunc(requestMessage.BodyData?.BodyAsBytes)); + } + + if (BodyDataFunc != null) + { + return MatchScores.ToScore(BodyDataFunc(requestMessage.BodyData)); + } + + return default; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageClientIPMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageClientIPMatcher.cs new file mode 100644 index 000000000..78d531fa5 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageClientIPMatcher.cs @@ -0,0 +1,100 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using AnyOfTypes; +using Stef.Validation; +using WireMock.Models; + +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; } + + /// + /// The + /// + public MatchBehaviour Behaviour { get; } + + /// + /// The + /// + public MatchOperator MatchOperator { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The to use. + /// The clientIPs. + public RequestMessageClientIPMatcher( + MatchBehaviour matchBehaviour, + MatchOperator matchOperator, + params string[] clientIPs) : + this(matchBehaviour, matchOperator, clientIPs + .Select(clientIP => new WildcardMatcher(matchBehaviour, new AnyOf[] { clientIP }, false, matchOperator)) + .Cast().ToArray()) + { + Behaviour = matchBehaviour; + MatchOperator = matchOperator; + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The to use. + /// The matchers. + public RequestMessageClientIPMatcher(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params IStringMatcher[] matchers) + { + Matchers = Guard.NotNull(matchers); + Behaviour = matchBehaviour; + MatchOperator = matchOperator; + } + + /// + /// Initializes a new instance of the class. + /// + /// The clientIP functions. + public RequestMessageClientIPMatcher(params Func[] funcs) + { + Funcs = Guard.NotNull(funcs); + } + + /// + 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 (Matchers != null) + { + var results = Matchers.Select(m => m.IsMatch(requestMessage.ClientIP)).ToArray(); + return MatchResult.From(results, MatchOperator); + } + + if (Funcs != null) + { + var results = Funcs.Select(func => func(requestMessage.ClientIP)).ToArray(); + return MatchScores.ToScore(results, MatchOperator); + } + + return default; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageCompositeMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageCompositeMatcher.cs new file mode 100644 index 000000000..b6c25a997 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageCompositeMatcher.cs @@ -0,0 +1,50 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; +using System.Linq; +using Stef.Validation; + +namespace WireMock.Matchers.Request; + +/// +/// The composite request matcher. +/// +public abstract class RequestMessageCompositeMatcher : IRequestMatcher +{ + private readonly CompositeMatcherType _type; + + /// + /// Gets the request matchers. + /// + /// + /// The request matchers. + /// + private IEnumerable RequestMatchers { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The request matchers. + /// The CompositeMatcherType type (Defaults to 'And') + protected RequestMessageCompositeMatcher(IEnumerable requestMatchers, CompositeMatcherType type = CompositeMatcherType.And) + { + RequestMatchers = Guard.NotNull(requestMatchers); + _type = type; + } + + /// + public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) + { + if (!RequestMatchers.Any()) + { + return MatchScores.Mismatch; + } + + if (_type == CompositeMatcherType.And) + { + return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult)); + } + + return RequestMatchers.Max(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult)); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageCookieMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageCookieMatcher.cs new file mode 100644 index 000000000..9613d48da --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageCookieMatcher.cs @@ -0,0 +1,130 @@ +// Copyright © WireMock.Net + +using Stef.Validation; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WireMock.Matchers.Request; + +/// +/// The request cookie matcher. +/// +/// +public class RequestMessageCookieMatcher : IRequestMatcher +{ + /// + /// 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; } + + /// + /// Initializes a new instance of the class. + /// + /// The name. + /// The pattern. + /// Ignore the case from the pattern. + /// The match behaviour. + public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, string name, string pattern, bool ignoreCase) + { + MatchBehaviour = matchBehaviour; + IgnoreCase = ignoreCase; + Name = Guard.NotNull(name); + Matchers = new IStringMatcher[] { new WildcardMatcher(matchBehaviour, Guard.NotNull(pattern), ignoreCase) }; + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The name. + /// The patterns. + /// Ignore the case from the pattern. + public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, string name, bool ignoreCase, params string[] patterns) : + this(matchBehaviour, 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 name. + /// The matchers. + /// Ignore the case from the pattern. + public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, string name, bool ignoreCase, params IStringMatcher[] matchers) + { + MatchBehaviour = matchBehaviour; + Name = Guard.NotNull(name); + Matchers = Guard.NotNull(matchers); + IgnoreCase = ignoreCase; + } + + /// + /// Initializes a new instance of the class. + /// + /// The funcs. + public RequestMessageCookieMatcher(params Func, bool>[] funcs) + { + Guard.NotNull(funcs); + + Funcs = 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.Cookies == null) + { + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); + } + + // Check if we want to use IgnoreCase to compare the Cookie-Name and Cookie-Value + var cookies = !IgnoreCase ? requestMessage.Cookies : new Dictionary(requestMessage.Cookies, StringComparer.OrdinalIgnoreCase); + + if (Funcs != null) + { + return MatchScores.ToScore(Funcs.Any(f => f(cookies))); + } + + if (Matchers == null) + { + return default; + } + + if (!cookies.ContainsKey(Name)) + { + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); + } + + return Matchers.Max(m => m.IsMatch(cookies[Name])); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageHeaderMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageHeaderMatcher.cs new file mode 100644 index 000000000..77a5f04ce --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageHeaderMatcher.cs @@ -0,0 +1,152 @@ +// 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 +{ + /// + /// 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 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 MatchScores.ToScore(funcResults, MatchOperator); + } + + if (Matchers != null) + { + if (!headers.ContainsKey(Name)) + { + return 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(resultsPerMatcher, MatchOperator.And)); + } + + return MatchResult.From(results, MatchOperator); + } + + return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageHttpVersionMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageHttpVersionMatcher.cs new file mode 100644 index 000000000..2de8c924f --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageHttpVersionMatcher.cs @@ -0,0 +1,88 @@ +// Copyright © WireMock.Net + +using System; +using System.Linq; +using Stef.Validation; + +namespace WireMock.Matchers.Request; + +/// +/// The request HTTP Version matcher. +/// +public class RequestMessageHttpVersionMatcher : IRequestMatcher +{ + /// + /// The matcher. + /// + public IStringMatcher? Matcher { get; } + + /// + /// The func. + /// + public Func? Func { get; } + + /// + /// The + /// + public MatchBehaviour Behaviour { get; } + + /// + /// The HTTP Version + /// + public string? HttpVersion { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The HTTP Version. + public RequestMessageHttpVersionMatcher(MatchBehaviour matchBehaviour, string httpVersion) : + this(matchBehaviour, new ExactMatcher(matchBehaviour, httpVersion)) + { + HttpVersion = httpVersion; + Behaviour = matchBehaviour; + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The matcher. + public RequestMessageHttpVersionMatcher(MatchBehaviour matchBehaviour, IStringMatcher matcher) + { + Matcher = Guard.NotNull(matcher); + Behaviour = matchBehaviour; + HttpVersion = matcher.GetPatterns().FirstOrDefault(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The function. + public RequestMessageHttpVersionMatcher(Func func) + { + Func = Guard.NotNull(func); + } + + /// + 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 (Matcher != null) + { + return Matcher.IsMatch(requestMessage.HttpVersion); + } + + if (Func != null) + { + return MatchScores.ToScore(Func(requestMessage.HttpVersion)); + } + + return default; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageMethodMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageMethodMatcher.cs new file mode 100644 index 000000000..36ff86c51 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageMethodMatcher.cs @@ -0,0 +1,49 @@ +// Copyright © WireMock.Net + +using System; +using System.Linq; +using Stef.Validation; + +namespace WireMock.Matchers.Request; + +/// +/// The request method matcher. +/// +internal class RequestMessageMethodMatcher : IRequestMatcher +{ + /// + /// The + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + /// The + /// + public MatchOperator MatchOperator { get; } + + /// + /// The methods + /// + public string[] Methods { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The to use. + /// The methods. + public RequestMessageMethodMatcher(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params string[] methods) + { + Methods = Guard.NotNull(methods); + MatchBehaviour = matchBehaviour; + MatchOperator = matchOperator; + } + + /// + public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) + { + var scores = Methods.Select(m => string.Equals(m, requestMessage.Method, StringComparison.OrdinalIgnoreCase)).ToArray(); + var score = MatchScores.ToScore(scores, MatchOperator); + return requestMatchResult.AddScore(GetType(), score, null); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageParamMatcher.cs new file mode 100644 index 000000000..03f0c93b4 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageParamMatcher.cs @@ -0,0 +1,147 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using Stef.Validation; +using WireMock.Types; + +namespace WireMock.Matchers.Request; + +/// +/// The request parameters matcher. +/// +public class RequestMessageParamMatcher : IRequestMatcher +{ + /// + /// MatchBehaviour + /// + public MatchBehaviour MatchBehaviour { get; } + + /// + /// The funcs + /// + public Func>, bool>[]? Funcs { get; } + + /// + /// The key + /// + public string Key { get; } = string.Empty; + + /// + /// Defines if the key should be matched using case-ignore. + /// + public bool IgnoreCase { get; } + + /// + /// The matchers. + /// + public IReadOnlyList? Matchers { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The key. + /// Defines if the key should be matched using case-ignore. + public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase) : this(matchBehaviour, key, ignoreCase, (IStringMatcher[]?)null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The values. + public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params string[]? values) : + this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, MatchOperator.And, value)).Cast().ToArray()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The key. + /// Defines if the key should be matched using case-ignore. + /// The matchers. + public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params IStringMatcher[]? matchers) + { + MatchBehaviour = matchBehaviour; + Key = Guard.NotNull(key); + IgnoreCase = ignoreCase; + Matchers = matchers; + } + + /// + /// Initializes a new instance of the class. + /// + /// The funcs. + public RequestMessageParamMatcher(params Func>, bool>[] funcs) + { + Funcs = Guard.NotNull(funcs); + } + + /// + public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) + { + var score = GetMatchScore(requestMessage); + return requestMatchResult.AddScore(GetType(), MatchBehaviourHelper.Convert(MatchBehaviour, score), null); + } + + private double GetMatchScore(IRequestMessage requestMessage) + { + if (Funcs != null) + { + return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query))); + } + + var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key, IgnoreCase); + if (valuesPresentInRequestMessage == null) + { + // Key is not present at all, just return Mismatch + return MatchScores.Mismatch; + } + + if (Matchers == null || !Matchers.Any()) + { + // Matchers are null or not defined, and Key is present, just return Perfect. + return MatchScores.Perfect; + } + + // Return the score based on Matchers and valuesPresentInRequestMessage + return CalculateScore(Matchers, valuesPresentInRequestMessage); + } + + private static double CalculateScore(IReadOnlyList matchers, WireMockList valuesPresentInRequestMessage) + { + var total = new List(); + + // If the total patterns in all matchers > values in message, use the matcher as base + if (matchers.Sum(m => m.GetPatterns().Length) > valuesPresentInRequestMessage.Count) + { + foreach (var matcher in matchers) + { + double score = 0d; + foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage) + { + score += matcher.IsMatch(valuePresentInRequestMessage).Score / matcher.GetPatterns().Length; + } + + total.Add(score); + } + } + else + { + foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage) + { + var score = matchers.Max(m => m.IsMatch(valuePresentInRequestMessage).Score); + total.Add(score); + } + } + + return total.Any() ? MatchScores.ToScore(total, MatchOperator.Average) : default; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs new file mode 100644 index 000000000..f342a767d --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageScenarioAndStateMatcher.cs @@ -0,0 +1,42 @@ +// Copyright © WireMock.Net + +namespace WireMock.Matchers.Request; + +/// +/// The scenario and state matcher. +/// +internal class RequestMessageScenarioAndStateMatcher : IRequestMatcher +{ + /// + /// Execution state condition for the current mapping. + /// + private readonly string? _executionConditionState; + + /// + /// The next state which will be signaled after the current mapping execution. + /// In case the value is null state will not be changed. + /// + private readonly string? _nextState; + + /// + /// Initializes a new instance of the class. + /// + /// The next state. + /// Execution state condition for the current mapping. + public RequestMessageScenarioAndStateMatcher(string? nextState, string? executionConditionState) + { + _nextState = nextState; + _executionConditionState = executionConditionState; + } + + /// + public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) + { + return requestMatchResult.AddScore(GetType(), GetScore(), null); + } + + private double GetScore() + { + return Equals(_executionConditionState, _nextState) ? MatchScores.Perfect : MatchScores.Mismatch; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/Request/RequestMessageUrlMatcher.cs b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageUrlMatcher.cs new file mode 100644 index 000000000..810afb599 --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/Request/RequestMessageUrlMatcher.cs @@ -0,0 +1,100 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Linq; +using AnyOfTypes; +using Stef.Validation; +using WireMock.Models; + +namespace WireMock.Matchers.Request; + +/// +/// The request url matcher. +/// +public class RequestMessageUrlMatcher : IRequestMatcher +{ + /// + /// The matchers + /// + public IReadOnlyList? Matchers { get; } + + /// + /// The url functions + /// + public Func[]? Funcs { get; } + + /// + /// The + /// + public MatchBehaviour Behaviour { get; } + + /// + /// The + /// + public MatchOperator MatchOperator { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The to use. + /// The urls. + public RequestMessageUrlMatcher( + MatchBehaviour matchBehaviour, + MatchOperator matchOperator, + params string[] urls) : + this(matchBehaviour, matchOperator, urls + .Select(url => new WildcardMatcher(matchBehaviour, new AnyOf[] { url }, false, matchOperator)) + .Cast().ToArray()) + { + Behaviour = matchBehaviour; + MatchOperator = matchOperator; + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The to use. (default = "Or") + /// The matchers. + public RequestMessageUrlMatcher(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params IStringMatcher[] matchers) + { + Matchers = Guard.NotNull(matchers); + Behaviour = matchBehaviour; + MatchOperator = matchOperator; + } + + /// + /// Initializes a new instance of the class. + /// + /// The url functions. + public RequestMessageUrlMatcher(params Func[] funcs) + { + Funcs = Guard.NotNull(funcs); + } + + /// + 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 (Matchers != null) + { + var results = Matchers.Select(m => m.IsMatch(requestMessage.Url)).ToArray(); + return MatchResult.From(results, MatchOperator); + } + + if (Funcs != null) + { + var results = Funcs.Select(func => func(requestMessage.Url)).ToArray(); + return MatchScores.ToScore(results, MatchOperator); + } + + return default; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Matchers/WildcardMatcher.cs b/src/WireMock.Net.Shared/Matchers/WildcardMatcher.cs new file mode 100644 index 000000000..2b5c6f62d --- /dev/null +++ b/src/WireMock.Net.Shared/Matchers/WildcardMatcher.cs @@ -0,0 +1,84 @@ +// Copyright © WireMock.Net + +using System.Linq; +using System.Text.RegularExpressions; +using AnyOfTypes; +using Stef.Validation; +using WireMock.Extensions; +using WireMock.Models; + +namespace WireMock.Matchers; + +/// +/// WildcardMatcher +/// +/// +public class WildcardMatcher : RegexMatcher +{ + private readonly AnyOf[] _patterns; + + /// + /// Initializes a new instance of the class. + /// + /// The pattern. + /// IgnoreCase + public WildcardMatcher(AnyOf pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The pattern. + /// IgnoreCase + public WildcardMatcher(MatchBehaviour matchBehaviour, AnyOf pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The patterns. + /// IgnoreCase + public WildcardMatcher(AnyOf[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The match behaviour. + /// The patterns. + /// IgnoreCase + /// The to use. (default = "Or") + public WildcardMatcher( + MatchBehaviour matchBehaviour, + AnyOf[] patterns, + bool ignoreCase = false, + MatchOperator matchOperator = MatchOperator.Or) : base(matchBehaviour, CreateArray(patterns), ignoreCase, true, matchOperator) + { + _patterns = Guard.NotNull(patterns); + } + + /// + public override AnyOf[] GetPatterns() + { + return _patterns; + } + + /// + public override string Name => nameof(WildcardMatcher); + + private static AnyOf[] CreateArray(AnyOf[] patterns) + { + return patterns + .Select(pattern => new AnyOf( + new StringPattern + { + Pattern = "^" + Regex.Escape(pattern.GetPattern()).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", + PatternAsFile = pattern.IsSecond ? pattern.Second.PatternAsFile : null + })) + .ToArray(); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Models/GraphQLSchemaDetails.cs b/src/WireMock.Net.Shared/Models/GraphQLSchemaDetails.cs similarity index 100% rename from src/WireMock.Net.Common/Models/GraphQLSchemaDetails.cs rename to src/WireMock.Net.Shared/Models/GraphQLSchemaDetails.cs diff --git a/src/WireMock.Net.Common/Models/StringPattern.cs b/src/WireMock.Net.Shared/Models/StringPattern.cs similarity index 100% rename from src/WireMock.Net.Common/Models/StringPattern.cs rename to src/WireMock.Net.Shared/Models/StringPattern.cs diff --git a/src/WireMock.Net.Shared/RegularExpressions/RegexExtended.cs b/src/WireMock.Net.Shared/RegularExpressions/RegexExtended.cs new file mode 100644 index 000000000..f3e5990bd --- /dev/null +++ b/src/WireMock.Net.Shared/RegularExpressions/RegexExtended.cs @@ -0,0 +1,91 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Stef.Validation; + +namespace WireMock.RegularExpressions; + +/// +/// Extension to the object, adding support for GUID tokens for matching on. +/// +#if !NETSTANDARD1_3 +[Serializable] +#endif +internal class RegexExtended : Regex +{ + /// + public RegexExtended(string pattern) : this(pattern, RegexOptions.None) + { + } + + /// + public RegexExtended(string pattern, RegexOptions options) : + this(pattern, options, InfiniteMatchTimeout) + { + } + + /// + public RegexExtended(string pattern, RegexOptions options, TimeSpan matchTimeout) : + base(ReplaceGuidPattern(pattern), options, matchTimeout) + { + } + +#if !NETSTANDARD1_3 && !NET8_0_OR_GREATER + /// + protected RegexExtended(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context) + { + } +#endif + // Dictionary of various Guid tokens with a corresponding regular expression pattern to use instead. + private static readonly Dictionary GuidTokenPatterns = new() + { + // Lower case format `B` Guid pattern + { @"\guidb", @"(\{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\})" }, + + // Upper case format `B` Guid pattern + { @"\GUIDB", @"(\{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\})" }, + + // Lower case format `D` Guid pattern + { @"\guidd", "([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12})" }, + + // Upper case format `D` Guid pattern + { @"\GUIDD", "([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12})" }, + + // Lower case format `N` Guid pattern + { @"\guidn", "([a-z0-9]{32})" }, + + // Upper case format `N` Guid pattern + { @"\GUIDN", "([A-Z0-9]{32})" }, + + // Lower case format `P` Guid pattern + { @"\guidp", @"(\([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\))" }, + + // Upper case format `P` Guid pattern + { @"\GUIDP", @"(\([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\))" }, + + // Lower case format `X` Guid pattern + { @"\guidx", @"(\{0x[a-f0-9]{8},0x[a-f0-9]{4},0x[a-f0-9]{4},\{(0x[a-f0-9]{2},){7}(0x[a-f0-9]{2})\}\})" }, + + // Upper case format `X` Guid pattern + { @"\GUIDX", @"(\{0x[A-F0-9]{8},0x[A-F0-9]{4},0x[A-F0-9]{4},\{(0x[A-F0-9]{2},){7}(0x[A-F0-9]{2})\}\})" }, + }; + + /// + /// Replaces all instances of valid GUID tokens with the correct regular expression to match. + /// + /// Pattern to replace token for. + private static string ReplaceGuidPattern(string pattern) + { + Guard.NotNull(pattern); + + foreach (var tokenPattern in GuidTokenPatterns) + { + pattern = pattern.Replace(tokenPattern.Key, tokenPattern.Value); + } + + return pattern; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/RequestBuilders/IBodyRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IBodyRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IBodyRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IBodyRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IClientIPRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IClientIPRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IClientIPRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IClientIPRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/ICookiesRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/ICookiesRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/ICookiesRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/ICookiesRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IHeadersRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IHeadersRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IHeadersRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IHeadersRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IHttpVersionBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IHttpVersionBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IHttpVersionBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IHttpVersionBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IMethodRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IMethodRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IMethodRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IMethodRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IParamsRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IParamsRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IParamsRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IParamsRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/IUrlAndPathRequestBuilder.cs b/src/WireMock.Net.Shared/RequestBuilders/IUrlAndPathRequestBuilder.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/IUrlAndPathRequestBuilder.cs rename to src/WireMock.Net.Shared/RequestBuilders/IUrlAndPathRequestBuilder.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.ClientIP.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.ClientIP.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.ClientIP.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.ClientIP.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.UsingMethods.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.UsingMethods.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.UsingMethods.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.UsingMethods.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithBody.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithBody.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithBody.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithBody.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithCookies.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithCookies.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithCookies.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithCookies.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithHeaders.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithHeaders.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithHeaders.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithHeaders.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithHttpVersion.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithHttpVersion.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithHttpVersion.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithHttpVersion.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithParam.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithParam.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithParam.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithParam.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithPath.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithPath.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithPath.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithPath.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.WithUrl.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.WithUrl.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.WithUrl.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.WithUrl.cs diff --git a/src/WireMock.Net.Common/RequestBuilders/Request.cs b/src/WireMock.Net.Shared/RequestBuilders/Request.cs similarity index 100% rename from src/WireMock.Net.Common/RequestBuilders/Request.cs rename to src/WireMock.Net.Shared/RequestBuilders/Request.cs diff --git a/src/WireMock.Net.Shared/RequestMessage.cs b/src/WireMock.Net.Shared/RequestMessage.cs new file mode 100644 index 000000000..dc346f5ac --- /dev/null +++ b/src/WireMock.Net.Shared/RequestMessage.cs @@ -0,0 +1,208 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +#if USE_ASPNETCORE +using System.Security.Cryptography.X509Certificates; +#endif +using Stef.Validation; +using WireMock.Models; +using WireMock.Owin; +using WireMock.Types; +using WireMock.Util; + +namespace WireMock; + +/// +/// The RequestMessage. +/// +public class RequestMessage : IRequestMessage +{ + /// + public string ClientIP { get; } + + /// + public string Url { get; } + + /// + public string AbsoluteUrl { get; } + + /// + public string? ProxyUrl { get; set; } + + /// + public DateTime DateTime { get; set; } + + /// + public string Path { get; } + + /// + public string AbsolutePath { get; } + + /// + public string[] PathSegments { get; } + + /// + public string[] AbsolutePathSegments { get; } + + /// + public string Method { get; } + + /// + public string HttpVersion { get; } + + /// + public IDictionary>? Headers { get; } + + /// + public IDictionary? Cookies { get; } + + /// + public IDictionary>? Query { get; } + + /// + public IDictionary>? QueryIgnoreCase { get; } + + /// + public string RawQuery { get; } + + /// + public IBodyData? BodyData { get; } + + /// + public string? Body { get; } + + /// + public object? BodyAsJson { get; set; } + + /// + public byte[]? BodyAsBytes { get; } + + /// + [Newtonsoft.Json.JsonIgnore] // Issue 1001 + public object? BodyAsMimeMessage { get; } + + /// + public string? DetectedBodyType { get; } + + /// + public string? DetectedBodyTypeFromContentType { get; } + + /// + public string? DetectedCompression { get; } + + /// + public string Host { get; } + + /// + public string Protocol { get; } + + /// + public int Port { get; } + + /// + public string Origin { get; } + +#if USE_ASPNETCORE + /// + public X509Certificate2? ClientCertificate { get; } +#endif + + /// + /// Used for Unit Testing + /// + internal RequestMessage( + UrlDetails urlDetails, + string method, + string clientIP, + IBodyData? bodyData = null, + IDictionary? headers = null, + IDictionary? cookies = null) : this(null, urlDetails, method, clientIP, bodyData, headers, cookies) + { + } + + internal RequestMessage( + IWireMockMiddlewareOptions? options, + UrlDetails urlDetails, + string method, + string clientIP, + IBodyData? bodyData = null, + IDictionary? headers = null, + IDictionary? cookies = null, + string httpVersion = "1.1" +#if USE_ASPNETCORE + , X509Certificate2? clientCertificate = null +#endif + ) + { + Guard.NotNull(urlDetails); + Guard.NotNull(method); + Guard.NotNull(clientIP); + + AbsoluteUrl = urlDetails.AbsoluteUrl.ToString(); + Url = urlDetails.Url.ToString(); + Protocol = urlDetails.Url.Scheme; + Host = urlDetails.Url.Host; + Port = urlDetails.Url.Port; + Origin = $"{Protocol}://{Host}:{Port}"; + + AbsolutePath = WebUtility.UrlDecode(urlDetails.AbsoluteUrl.AbsolutePath); + Path = WebUtility.UrlDecode(urlDetails.Url.AbsolutePath); + PathSegments = Path.Split('/').Skip(1).ToArray(); + AbsolutePathSegments = AbsolutePath.Split('/').Skip(1).ToArray(); + + Method = method; + HttpVersion = httpVersion; + ClientIP = clientIP; + + BodyData = bodyData; + + // Convenience getters for e.g. Handlebars + Body = BodyData?.BodyAsString; + BodyAsJson = BodyData?.BodyAsJson; + BodyAsBytes = BodyData?.BodyAsBytes; + + DetectedBodyType = BodyData?.DetectedBodyType.ToString(); + DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString(); + DetectedCompression = BodyData?.DetectedCompression; + + Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList(header.Value)); + Cookies = cookies; + RawQuery = urlDetails.Url.Query; + Query = QueryStringParser.Parse(RawQuery, options?.QueryParameterMultipleValueSupport); + QueryIgnoreCase = new Dictionary>(Query, StringComparer.OrdinalIgnoreCase); + +#if USE_ASPNETCORE + ClientCertificate = clientCertificate; +#endif + + try + { + if (TypeLoader.TryFindType(out _) && TypeLoader.Load().TryGetMimeMessage(this, out var mimeMessage)) + { + BodyAsMimeMessage = mimeMessage; + } + } + catch + { + // Ignore exception from IMimeKitUtils.TryGetMimeMessage + } + } + + /// + public WireMockList? GetParameter(string key, bool ignoreCase = false) + { + if (Query == null) + { + return null; + } + + var query = !ignoreCase ? Query : new Dictionary>(Query, StringComparer.OrdinalIgnoreCase); + + return query.ContainsKey(key) ? query[key] : null; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/ResponseProviders/IResponseProvider.cs b/src/WireMock.Net.Shared/ResponseProviders/IResponseProvider.cs new file mode 100644 index 000000000..b82b2730c --- /dev/null +++ b/src/WireMock.Net.Shared/ResponseProviders/IResponseProvider.cs @@ -0,0 +1,23 @@ +// Copyright © WireMock.Net and mock4net by Alexandre Victoor + +// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. +// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. +using System.Threading.Tasks; +using WireMock.Settings; + +namespace WireMock.ResponseProviders; + +/// +/// The Response Provider interface. +/// +public interface IResponseProvider +{ + /// + /// The provide response. + /// + /// The used mapping. + /// The request. + /// The WireMockServerSettings. + /// The including a new (optional) . + Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings); +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/HttpClientSettings.cs b/src/WireMock.Net.Shared/Settings/HttpClientSettings.cs new file mode 100644 index 000000000..16a362953 --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/HttpClientSettings.cs @@ -0,0 +1,32 @@ +// Copyright © WireMock.Net + +using System.Security.Cryptography.X509Certificates; + +namespace WireMock.Settings; + +/// +/// HttpClientSettings +/// +public abstract class HttpClientSettings +{ + /// + /// The clientCertificate thumbprint or subject name fragment to use. + /// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com"" + /// + public string? ClientX509Certificate2ThumbprintOrSubjectName { get; set; } + + /// + /// Defines the WebProxySettings. + /// + public WebProxySettings? WebProxySettings { get; set; } + + /// + /// Proxy requests should follow redirection (30x). + /// + public bool? AllowAutoRedirect { get; set; } + + /// + /// The to use. + /// + public X509Certificate2? Certificate { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/ProxyAndRecordSettings.cs b/src/WireMock.Net.Shared/Settings/ProxyAndRecordSettings.cs new file mode 100644 index 000000000..dca669b28 --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/ProxyAndRecordSettings.cs @@ -0,0 +1,115 @@ +// Copyright © WireMock.Net + +using JetBrains.Annotations; + +namespace WireMock.Settings; + +/// +/// ProxyAndRecordSettings +/// +public class ProxyAndRecordSettings : HttpClientSettings +{ + /// + /// Default prefix value for saved mapping file + /// + public const string DefaultPrefixForSavedMappingFile = "Proxy Mapping for "; + + /// + /// The URL to proxy. + /// + [PublicAPI] + public string Url { get; set; } = null!; + + /// + /// Save the mapping for each request/response to the internal Mappings. + /// + [PublicAPI] + public bool SaveMapping { get; set; } + + /// + /// Save the mapping for each request/response also to a file. (Note that SaveMapping must also be set to true.) + /// + [PublicAPI] + public bool SaveMappingToFile { get; set; } + + /// + /// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.) + /// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported. + /// + /// Deprecated : use SaveMappingSettings. + /// + [PublicAPI] + public string SaveMappingForStatusCodePattern + { + set + { + if (SaveMappingSettings is null) + { + SaveMappingSettings = new ProxySaveMappingSettings(); + } + + SaveMappingSettings.StatusCodePattern = value; + } + } + + /// + /// Additional SaveMappingSettings. + /// + [PublicAPI] + public ProxySaveMappingSettings? SaveMappingSettings { get; set; } + + /// + /// Defines a list from headers which will be excluded from the saved mappings. + /// + [PublicAPI] + public string[]? ExcludedHeaders { get; set; } + + /// + /// Defines a list of params which will be excluded from the saved mappings. + /// + [PublicAPI] + public string[]? ExcludedParams { get; set; } + + /// + /// Defines a list of cookies which will be excluded from the saved mappings. + /// + [PublicAPI] + public string[]? ExcludedCookies { get; set; } + + /// + /// Replace Settings + /// + [PublicAPI] + public ProxyUrlReplaceSettings? ReplaceSettings { get; set; } + + /// + /// Prefer the Proxy Mapping over the saved Mapping (in case SaveMapping is set to true). + /// + //[PublicAPI] + //public bool PreferProxyMapping { get; set; } + + /// + /// When SaveMapping is set to true, this setting can be used to control the behavior of the generated request matchers for the new mapping. + /// - false, the default matchers will be used. + /// - true, the defined mappings in the request wil be used for the new mapping. + /// + /// Default value is false. + /// + public bool UseDefinedRequestMatchers { get; set; } + + /// + /// Append an unique GUID to the filename from the saved mapping file. + /// + public bool AppendGuidToSavedMappingFile { get; set; } + + /// + /// Set prefix for saved mapping file. + /// + public string PrefixForSavedMappingFile { get; set; } = DefaultPrefixForSavedMappingFile; + + /// + /// Proxy all Api calls, irrespective of any condition + /// + [PublicAPI] + public bool ProxyAll { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/ProxySaveMappingSetting.cs b/src/WireMock.Net.Shared/Settings/ProxySaveMappingSetting.cs new file mode 100644 index 000000000..1d4f4db4a --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/ProxySaveMappingSetting.cs @@ -0,0 +1,50 @@ +// Copyright © WireMock.Net + +using System; +using Stef.Validation; +using WireMock.Matchers; + +namespace WireMock.Settings; + +/// +/// Represents settings for saving a proxy mapping with a non-nullable value and a specific match behaviour. +/// +/// The non-nullable type of the value associated with the proxy save mapping setting. +public class ProxySaveMappingSetting where T : notnull +{ + /// + /// Gets the match behaviour for the proxy save mapping setting. + /// + /// The match behaviour which determines how matches are evaluated. + public MatchBehaviour MatchBehaviour { get; } + + /// + /// Gets the non-nullable value associated with the proxy save mapping setting. + /// + /// The value of type . + public T Value { get; } + + /// + /// Initializes a new instance of the class with specified non-nullable value and match behaviour. + /// + /// The non-nullable value of type . + /// The match behaviour (optional, default is MatchBehaviour.AcceptOnMatch. + /// Thrown if the is null. + public ProxySaveMappingSetting(T value, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) + { + Value = Guard.NotNull(value); + MatchBehaviour = matchBehaviour; + } + + /// + /// Converts a non-nullable value of type to a implicitly. + /// + /// The non-nullable value to convert. + public static implicit operator ProxySaveMappingSetting(T value) => new(value); + + /// + /// Converts a to its underlying non-nullable value of type implicitly. + /// + /// The to convert. + public static implicit operator T(ProxySaveMappingSetting instance) => instance.Value; +} diff --git a/src/WireMock.Net.Shared/Settings/ProxySaveMappingSettings.cs b/src/WireMock.Net.Shared/Settings/ProxySaveMappingSettings.cs new file mode 100644 index 000000000..3a9a5a6de --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/ProxySaveMappingSettings.cs @@ -0,0 +1,24 @@ +// Copyright © WireMock.Net + +using JetBrains.Annotations; + +namespace WireMock.Settings; + +/// +/// ProxySaveMappingSettings +/// +public class ProxySaveMappingSettings +{ + /// + /// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.) + /// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported. + /// + [PublicAPI] + public ProxySaveMappingSetting? StatusCodePattern { get; set; } = "*"; + + /// + /// Only save these Http Methods. (Note that SaveMapping must also be set to true.) + /// + [PublicAPI] + public ProxySaveMappingSetting? HttpMethods { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/ProxyUrlReplaceSettings.cs b/src/WireMock.Net.Shared/Settings/ProxyUrlReplaceSettings.cs new file mode 100644 index 000000000..a9de5d8c1 --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/ProxyUrlReplaceSettings.cs @@ -0,0 +1,24 @@ +// Copyright © WireMock.Net + +namespace WireMock.Settings; + +/// +/// Defines an old path param and a new path param to be replaced when proxying. +/// +public class ProxyUrlReplaceSettings +{ + /// + /// The old path value to be replaced by the new path value + /// + public string OldValue { get; set; } = null!; + + /// + /// The new path value to replace the old value with + /// + public string NewValue { get; set; } = null!; + + /// + /// Defines if the case should be ignore when replacing. + /// + public bool IgnoreCase { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/WebProxySettings.cs b/src/WireMock.Net.Shared/Settings/WebProxySettings.cs new file mode 100644 index 000000000..2002164bf --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/WebProxySettings.cs @@ -0,0 +1,29 @@ +// Copyright © WireMock.Net + +using JetBrains.Annotations; + +namespace WireMock.Settings; + +/// +/// WebProxySettings +/// +public class WebProxySettings +{ + /// + /// A string instance that contains the address of the proxy server. + /// + [PublicAPI] + public string Address { get; set; } = null!; + + /// + /// The user name associated with the credentials. + /// + [PublicAPI] + public string? UserName { get; set; } + + /// + /// The password for the user name associated with the credentials. + /// + [PublicAPI] + public string? Password { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/WebhookSettings.cs b/src/WireMock.Net.Shared/Settings/WebhookSettings.cs new file mode 100644 index 000000000..799600330 --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/WebhookSettings.cs @@ -0,0 +1,10 @@ +// Copyright © WireMock.Net + +namespace WireMock.Settings; + +/// +/// WebhookSettings +/// +public class WebhookSettings : HttpClientSettings +{ +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/WireMockCertificateSettings.cs b/src/WireMock.Net.Shared/Settings/WireMockCertificateSettings.cs new file mode 100644 index 000000000..c9ae39efb --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/WireMockCertificateSettings.cs @@ -0,0 +1,55 @@ +// Copyright © WireMock.Net + +using JetBrains.Annotations; + +namespace WireMock.Settings; + +/// +/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used. +/// +/// X509StoreName and X509StoreLocation should be defined +/// OR +/// X509CertificateFilePath and X509CertificatePassword should be defined +/// +public class WireMockCertificateSettings +{ + /// + /// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher) + /// + [PublicAPI] + public string? X509StoreName { get; set; } + + /// + /// X509 StoreLocation (CurrentUser or LocalMachine) + /// + [PublicAPI] + public string? X509StoreLocation { get; set; } + + /// + /// X509 Thumbprint or SubjectName (if not defined, the 'host' is used) + /// + [PublicAPI] + public string? X509StoreThumbprintOrSubjectName { get; set; } + + /// + /// X509Certificate FilePath + /// + [PublicAPI] + public string? X509CertificateFilePath { get; set; } + + /// + /// X509Certificate Password + /// + [PublicAPI] + public string? X509CertificatePassword { get; set; } + + /// + /// X509StoreName and X509StoreLocation should be defined + /// OR + /// X509CertificateFilePath and X509CertificatePassword should be defined + /// + [PublicAPI] + public bool IsDefined => + !string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) || + !string.IsNullOrEmpty(X509CertificateFilePath); +} \ No newline at end of file diff --git a/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs b/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs new file mode 100644 index 000000000..74e8f2ed3 --- /dev/null +++ b/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs @@ -0,0 +1,331 @@ +// Copyright © WireMock.Net + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using HandlebarsDotNet; +using JetBrains.Annotations; +using Newtonsoft.Json; +using WireMock.Admin.Mappings; +using WireMock.Handlers; +using WireMock.Logging; +using WireMock.Matchers; +using WireMock.Types; +using System.Globalization; +using WireMock.Models; +#if USE_ASPNETCORE +using Microsoft.Extensions.DependencyInjection; +#endif + +namespace WireMock.Settings; + +/// +/// WireMockServerSettings +/// +public class WireMockServerSettings +{ + internal const int DefaultStartTimeout = 10000; + + /// + /// Gets or sets the http port. + /// + [PublicAPI] + public int? Port { get; set; } + + /// + /// Gets or sets the use SSL. + /// + // ReSharper disable once InconsistentNaming + [PublicAPI] + public bool? UseSSL { get; set; } + + /// + /// Defines on which scheme (http/https) to host. (This overrides the UseSSL value). + /// + [PublicAPI] + public HostingScheme? HostingScheme { get; set; } + + /// + /// Gets or sets to use HTTP 2 (used for Grpc). + /// + [PublicAPI] + public bool? UseHttp2 { get; set; } + + /// + /// Gets or sets whether to start admin interface. + /// + [PublicAPI] + public bool? StartAdminInterface { get; set; } + + /// + /// Gets or sets if the static mappings should be read at startup. + /// + [PublicAPI] + public bool? ReadStaticMappings { get; set; } + + /// + /// Watch the static mapping files + folder for changes when running. + /// + [PublicAPI] + public bool? WatchStaticMappings { get; set; } + + /// + /// A value indicating whether subdirectories within the static mappings path should be monitored. + /// + [PublicAPI] + public bool? WatchStaticMappingsInSubdirectories { get; set; } + + /// + /// Gets or sets if the proxy and record settings. + /// + [PublicAPI] + public ProxyAndRecordSettings? ProxyAndRecordSettings { get; set; } + + /// + /// Gets or sets the urls. + /// + [PublicAPI] + public string[]? Urls { get; set; } + + /// + /// StartTimeout + /// + [PublicAPI] + public int StartTimeout { get; set; } = DefaultStartTimeout; + + /// + /// Allow Partial Mapping (default set to false). + /// + [PublicAPI] + public bool? AllowPartialMapping { get; set; } + + /// + /// The username needed for __admin access. + /// + [PublicAPI] + public string? AdminUsername { get; set; } + + /// + /// The password needed for __admin access. + /// + [PublicAPI] + public string? AdminPassword { get; set; } + + /// + /// The AzureAD Tenant needed for __admin access. + /// + [PublicAPI] + public string? AdminAzureADTenant { get; set; } + + /// + /// The AzureAD Audience / Resource for __admin access. + /// + [PublicAPI] + public string? AdminAzureADAudience { get; set; } + + /// + /// The RequestLog expiration in hours (optional). + /// + [PublicAPI] + public int? RequestLogExpirationDuration { get; set; } + + /// + /// The MaxRequestLog count (optional). + /// + [PublicAPI] + public int? MaxRequestLogCount { get; set; } + + /// + /// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional] + /// + [PublicAPI] + [JsonIgnore] + public Action? PreWireMockMiddlewareInit { get; set; } + + /// + /// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional] + /// + [PublicAPI] + [JsonIgnore] + public Action? PostWireMockMiddlewareInit { get; set; } + +#if USE_ASPNETCORE + /// + /// Action which is called with IServiceCollection when ASP.NET Core DI is being configured. [Optional] + /// + [PublicAPI] + [JsonIgnore] + public Action? AdditionalServiceRegistration { get; set; } + + /// + /// Policies to use when using CORS. By default CORS is disabled. [Optional] + /// + [PublicAPI] + public CorsPolicyOptions? CorsPolicyOptions { get; set; } +#endif + + /// + /// The IWireMockLogger which logs Debug, Info, Warning or Error + /// + [PublicAPI] + [JsonIgnore] + public IWireMockLogger Logger { get; set; } = null!; + + /// + /// Handler to interact with the file system to read and write static mapping files. + /// + [PublicAPI] + [JsonIgnore] + public IFileSystemHandler FileSystemHandler { get; set; } = null!; + + /// + /// Action which can be used to add additional Handlebars registrations. [Optional] + /// + [PublicAPI] + [JsonIgnore] + public Action? HandlebarsRegistrationCallback { get; set; } + + /// + /// Allow the usage of CSharpCodeMatcher (default is not allowed). + /// + [PublicAPI] + public bool? AllowCSharpCodeMatcher { get; set; } + + /// + /// Allow a Body for all HTTP Methods. (default set to false). + /// + [PublicAPI] + public bool? AllowBodyForAllHttpMethods { get; set; } + + /// + /// Allow only a HttpStatus Code in the response which is defined. (default set to false). + /// - false : also null, 0, empty or invalid HttpStatus codes are allowed. + /// - true : only codes defined in are allowed. + /// + [PublicAPI] + public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } + + /// + /// Set to true to disable Json deserialization when processing requests. (default set to false). + /// + [PublicAPI] + public bool? DisableJsonBodyParsing { get; set; } + + /// + /// Disable support for GZip and Deflate request body decompression. (default set to false). + /// + [PublicAPI] + public bool? DisableRequestBodyDecompressing { get; set; } + + /// + /// Set to true to disable FormUrlEncoded deserializing when processing requests. (default set to false). + /// + [PublicAPI] + public bool? DisableDeserializeFormUrlEncoded { get; set; } + + /// + /// Handle all requests synchronously. (default set to false). + /// + [PublicAPI] + public bool? HandleRequestsSynchronously { get; set; } + + /// + /// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used. + /// + /// X509StoreName and X509StoreLocation should be defined + /// OR + /// X509CertificateFilePath and X509CertificatePassword should be defined + /// + [PublicAPI] + public WireMockCertificateSettings? CertificateSettings { get; set; } + + /// + /// Defines if custom CertificateSettings are defined + /// + [PublicAPI] + public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true; + +#if USE_ASPNETCORE + /// + /// Client certificate mode for the server + /// + [PublicAPI] + public ClientCertificateMode ClientCertificateMode { get; set; } + + /// + /// Whether to accept any client certificate + /// + public bool AcceptAnyClientCertificate { get; set; } +#endif + + /// + /// Defines the global IWebhookSettings to use. + /// + [PublicAPI] + public WebhookSettings? WebhookSettings { get; set; } + + /// + /// Use the RegexExtended.cs instead of the default (default set to true). + /// + [PublicAPI] + public bool? UseRegexExtended { get; set; } = true; + + /// + /// Save unmatched requests to a file using the (default set to false). + /// + [PublicAPI] + public bool? SaveUnmatchedRequests { get; set; } + + /// + /// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false). + /// + [PublicAPI] + public bool? DoNotSaveDynamicResponseInLogEntry { get; set; } + + /// + /// See . + /// + /// Default value = "All". + /// + [PublicAPI] + public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; } + + /// + /// Custom matcher mappings for static mappings + /// + [PublicAPI, JsonIgnore] + public IDictionary>? CustomMatcherMappings { get; set; } + + /// + /// The used when the a JSON response is generated. + /// + [PublicAPI, JsonIgnore] + public JsonSerializerSettings? JsonSerializerSettings { get; set; } + + /// + /// The Culture to use. + /// Currently used for: + /// - Handlebars Transformer + /// + [JsonIgnore] + public CultureInfo Culture { get; set; } = CultureInfo.CurrentCulture; + + /// + /// A list of Grpc ProtoDefinitions which can be used. + /// + [PublicAPI] + public Dictionary? ProtoDefinitions { get; set; } + + /// + /// A list of GraphQL Schemas which can be used. + /// + [PublicAPI] + public Dictionary? GraphQLSchemas { get; set; } + + /// + /// The admin path to use for accessing the Admin REST interface. + /// If not set __/admin is used. + /// + [PublicAPI] + public string? AdminPath { get; set; } +} \ No newline at end of file diff --git a/src/WireMock.Net.Common/Util/ReflectionUtils.cs b/src/WireMock.Net.Shared/Util/ReflectionUtils.cs similarity index 100% rename from src/WireMock.Net.Common/Util/ReflectionUtils.cs rename to src/WireMock.Net.Shared/Util/ReflectionUtils.cs diff --git a/src/WireMock.Net.Common/Util/TypeLoader.cs b/src/WireMock.Net.Shared/Util/TypeLoader.cs similarity index 100% rename from src/WireMock.Net.Common/Util/TypeLoader.cs rename to src/WireMock.Net.Shared/Util/TypeLoader.cs diff --git a/src/WireMock.Net.Common/WireMock.Net.Common.csproj b/src/WireMock.Net.Shared/WireMock.Net.Shared.csproj similarity index 63% rename from src/WireMock.Net.Common/WireMock.Net.Common.csproj rename to src/WireMock.Net.Shared/WireMock.Net.Shared.csproj index 6663da67d..7261fcc69 100644 --- a/src/WireMock.Net.Common/WireMock.Net.Common.csproj +++ b/src/WireMock.Net.Shared/WireMock.Net.Shared.csproj @@ -25,9 +25,15 @@ true + + $(DefineConstants);USE_ASPNETCORE + + - + + + + @@ -65,36 +75,36 @@ - + - - Request.cs - - - Request.cs - - - Request.cs - - - Request.cs - - - Request.cs - - - Request.cs - - - Request.cs - - - Request.cs - - - Request.cs - + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs + + + Request.cs +