Add Grpc ProtoBuf support (request-response) (#1047)

* ProtoBuf

* .

* x

* ---

* x

* fx

* ...

* sc

* ...

* .

* groen

* x

* fix tests

* ok!?

* fix tests

* fix tests

* !

* x

* 6

* .

* x

* ivaluematcher

* transformer

* .

* sc

* .

* mapping

* x

* tra

* com

* ...

* .

* .

* .

* AddProtoDefinition

* .

* set

* grpahj

* .

* .

* IdOrText

* ...

* async

* async2

* .

* t

* nuget

* <PackageReference Include="ProtoBufJsonConverter" Version="0.2.0-preview-04" />

* http version

* tests

* .WithHttpVersion("2")

* <PackageReference Include="ProtoBufJsonConverter" Version="0.2.0" />

* HttpVersionParser
This commit is contained in:
Stef Heyenrath
2024-02-16 17:16:51 +01:00
committed by GitHub
parent 801546fae7
commit 6ac95cf57d
129 changed files with 4585 additions and 1556 deletions

View File

@@ -184,4 +184,21 @@ public interface IRespondWithAProvider
/// <param name="probability">The probability when this request should be matched. Value is between 0 and 1.</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithProbability(double probability);
/// <summary>
/// Define a Grpc ProtoDefinition which is used for the request and the response.
/// This can be a ProtoDefinition as a string, or an id when the ProtoDefinitions are defined at the WireMockServer.
/// </summary>
/// <param name="protoDefinitionOrId">The proto definition as text or as id.</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithProtoDefinition(string protoDefinitionOrId);
/// <summary>
/// Define a GraphQL Schema which is used for the request and the response.
/// This can be a GraphQL Schema as a string, or an id when the GraphQL Schema are defined at the WireMockServer.
/// </summary>
/// <param name="graphQLSchemaOrId">The GraphQL Schema as text or as id.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. [optional]</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithGraphQLSchema(string graphQLSchemaOrId, IDictionary<string, Type>? customScalars = null);
}

View File

@@ -2,7 +2,6 @@
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Stef.Validation;
using WireMock.Matchers.Request;
using WireMock.Models;
@@ -34,6 +33,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
private int _timesInSameState = 1;
private bool? _useWebhookFireAndForget;
private double? _probability;
private IdOrText? _protoDefinition;
private GraphQLSchemaDetails? _graphQLSchemaDetails;
public Guid Guid { get; private set; }
@@ -76,7 +77,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
/// <param name="provider">The provider.</param>
public void RespondWith(IResponseProvider provider)
{
var mapping = new Mapping(
var mapping = new Mapping
(
Guid,
_dateTimeUtils.UtcNow,
_title,
@@ -93,14 +95,23 @@ internal class RespondWithAProvider : IRespondWithAProvider
Webhooks,
_useWebhookFireAndForget,
TimeSettings,
Data,
_probability);
Data
);
if (_probability != null)
{
mapping.WithProbability(_probability.Value);
}
if (_protoDefinition != null)
{
mapping.WithProtoDefinition(_protoDefinition.Value);
}
_registrationCallback(mapping, _saveToFile);
}
/// <inheritdoc />
[PublicAPI]
public IRespondWithAProvider WithData(object data)
{
Data = data;
@@ -117,7 +128,6 @@ internal class RespondWithAProvider : IRespondWithAProvider
public IRespondWithAProvider WithGuid(Guid guid)
{
Guid = guid;
return this;
}
@@ -133,7 +143,6 @@ internal class RespondWithAProvider : IRespondWithAProvider
public IRespondWithAProvider WithDescription(string description)
{
_description = description;
return this;
}
@@ -141,7 +150,6 @@ internal class RespondWithAProvider : IRespondWithAProvider
public IRespondWithAProvider WithPath(string path)
{
_path = path;
return this;
}
@@ -149,15 +157,13 @@ internal class RespondWithAProvider : IRespondWithAProvider
public IRespondWithAProvider AtPriority(int priority)
{
_priority = priority;
return this;
}
/// <inheritdoc />
public IRespondWithAProvider InScenario(string scenario)
{
_scenario = scenario;
_scenario = Guard.NotNullOrWhiteSpace(scenario);
return this;
}
@@ -209,9 +215,7 @@ internal class RespondWithAProvider : IRespondWithAProvider
/// <inheritdoc />
public IRespondWithAProvider WithTimeSettings(ITimeSettings timeSettings)
{
Guard.NotNull(timeSettings, nameof(timeSettings));
TimeSettings = timeSettings;
TimeSettings = Guard.NotNull(timeSettings);
return this;
}
@@ -219,10 +223,9 @@ internal class RespondWithAProvider : IRespondWithAProvider
/// <inheritdoc />
public IRespondWithAProvider WithWebhook(params IWebhook[] webhooks)
{
Guard.HasNoNulls(webhooks, nameof(webhooks));
Guard.HasNoNulls(webhooks);
Webhooks = webhooks;
return this;
}
@@ -283,13 +286,45 @@ internal class RespondWithAProvider : IRespondWithAProvider
public IRespondWithAProvider WithWebhookFireAndForget(bool useWebhooksFireAndForget)
{
_useWebhookFireAndForget = useWebhooksFireAndForget;
return this;
}
public IRespondWithAProvider WithProbability(double probability)
{
_probability = Guard.Condition(probability, p => p is >= 0 and <= 1.0);
return this;
}
/// <inheritdoc />
public IRespondWithAProvider WithProtoDefinition(string protoDefinitionOrId)
{
Guard.NotNullOrWhiteSpace(protoDefinitionOrId);
if (_settings.ProtoDefinitions?.TryGetValue(protoDefinitionOrId, out var protoDefinition) == true)
{
_protoDefinition = new (protoDefinitionOrId, protoDefinition);
}
else
{
_protoDefinition = new(null, protoDefinitionOrId);
}
return this;
}
/// <inheritdoc />
public IRespondWithAProvider WithGraphQLSchema(string graphQLSchemaOrId, IDictionary<string, Type>? customScalars = null)
{
Guard.NotNullOrWhiteSpace(graphQLSchemaOrId);
if (_settings.GraphQLSchemas?.TryGetValue(graphQLSchemaOrId, out _graphQLSchemaDetails) != true)
{
_graphQLSchemaDetails = new GraphQLSchemaDetails
{
SchemaAsString = graphQLSchemaOrId,
CustomScalars = customScalars
};
}
return this;
}
@@ -299,7 +334,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
string method,
IDictionary<string, WireMockList<string>>? headers,
bool useTransformer,
TransformerType transformerType)
TransformerType transformerType
)
{
return new Webhook
{

View File

@@ -231,9 +231,11 @@ public partial class WireMockServer
DisableRequestBodyDecompressing = _settings.DisableRequestBodyDecompressing,
DoNotSaveDynamicResponseInLogEntry = _settings.DoNotSaveDynamicResponseInLogEntry,
GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds,
// GraphQLSchemas TODO
HandleRequestsSynchronously = _settings.HandleRequestsSynchronously,
HostingScheme = _settings.HostingScheme,
MaxRequestLogCount = _settings.MaxRequestLogCount,
ProtoDefinitions = _settings.ProtoDefinitions,
QueryParameterMultipleValueSupport = _settings.QueryParameterMultipleValueSupport,
ReadStaticMappings = _settings.ReadStaticMappings,
RequestLogExpirationDuration = _settings.RequestLogExpirationDuration,
@@ -268,6 +270,7 @@ public partial class WireMockServer
_settings.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
_settings.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
_settings.MaxRequestLogCount = settings.MaxRequestLogCount;
_settings.ProtoDefinitions = settings.ProtoDefinitions;
_settings.ProxyAndRecordSettings = TinyMapperUtils.Instance.Map(settings.ProxyAndRecordSettings);
_settings.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
_settings.ReadStaticMappings = settings.ReadStaticMappings;

View File

@@ -195,6 +195,11 @@ public partial class WireMockServer
requestBuilder = requestBuilder.UsingMethod(matchBehaviour, matchOperator, requestModel.Methods);
}
if (requestModel.HttpVersion != null)
{
requestBuilder = requestBuilder.WithHttpVersion(requestModel.HttpVersion);
}
if (requestModel.Headers != null)
{
foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null))

View File

@@ -7,6 +7,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using AnyOfTypes;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Stef.Validation;
@@ -18,6 +19,7 @@ using WireMock.Handlers;
using WireMock.Http;
using WireMock.Logging;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.Owin;
using WireMock.RequestBuilders;
using WireMock.ResponseProviders;
@@ -209,19 +211,38 @@ public partial class WireMockServer : IWireMockServer
return new WireMockServer(settings);
}
/// <summary>
/// Starts this WireMockServer with the specified settings.
/// </summary>
/// <param name="action">The action to configure the WireMockServerSettings.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start(Action<WireMockServerSettings> action)
{
Guard.NotNull(action);
var settings = new WireMockServerSettings();
action(settings);
return new WireMockServer(settings);
}
/// <summary>
/// Start this WireMockServer.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="ssl">The SSL support.</param>
/// <param name="useSSL">The SSL support.</param>
/// <param name="useHttp2">Use HTTP 2 (needed for Grpc).</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start(int? port = 0, bool ssl = false)
public static WireMockServer Start(int? port = 0, bool useSSL = false, bool useHttp2 = false)
{
return new WireMockServer(new WireMockServerSettings
{
Port = port,
UseSSL = ssl
UseSSL = useSSL,
UseHttp2 = useHttp2
});
}
@@ -245,15 +266,17 @@ public partial class WireMockServer : IWireMockServer
/// Start this WireMockServer with the admin interface.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="ssl">The SSL support.</param>
/// <param name="useSSL">The SSL support.</param>
/// <param name="useHttp2">Use HTTP 2 (needed for Grpc).</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterface(int? port = 0, bool ssl = false)
public static WireMockServer StartWithAdminInterface(int? port = 0, bool useSSL = false, bool useHttp2 = false)
{
return new WireMockServer(new WireMockServerSettings
{
Port = port,
UseSSL = ssl,
UseSSL = useSSL,
UseHttp2 = useHttp2,
StartAdminInterface = true
});
}
@@ -266,7 +289,7 @@ public partial class WireMockServer : IWireMockServer
[PublicAPI]
public static WireMockServer StartWithAdminInterface(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
Guard.NotNullOrEmpty(urls);
return new WireMockServer(new WireMockServerSettings
{
@@ -329,6 +352,7 @@ public partial class WireMockServer : IWireMockServer
urlOptions = new HostUrlOptions
{
HostingScheme = settings.HostingScheme.Value,
UseHttp2 = settings.UseHttp2,
Port = settings.Port
};
}
@@ -337,6 +361,7 @@ public partial class WireMockServer : IWireMockServer
urlOptions = new HostUrlOptions
{
HostingScheme = settings.UseSSL == true ? HostingScheme.Https : HostingScheme.Http,
UseHttp2 = settings.UseHttp2,
Port = settings.Port
};
}
@@ -573,6 +598,49 @@ public partial class WireMockServer : IWireMockServer
return _mappingBuilder.Given(requestMatcher, saveToFile);
}
/// <summary>
/// Add a Grpc ProtoDefinition at server-level.
/// </summary>
/// <param name="id">Unique identifier for the ProtoDefinition.</param>
/// <param name="protoDefinition">The ProtoDefinition as text.</param>
/// <returns><see cref="WireMockServer"/></returns>
[PublicAPI]
public WireMockServer AddProtoDefinition(string id, string protoDefinition)
{
Guard.NotNullOrWhiteSpace(id);
Guard.NotNullOrWhiteSpace(protoDefinition);
_settings.ProtoDefinitions ??= new Dictionary<string, string>();
_settings.ProtoDefinitions[id] = protoDefinition;
return this;
}
/// <summary>
/// Add a GraphQL Schema at server-level.
/// </summary>
/// <param name="id">Unique identifier for the GraphQL Schema.</param>
/// <param name="graphQLSchema">The GraphQL Schema as string or StringPattern.</param>
/// <param name="customScalars">A dictionary defining the custom scalars used in this schema. [optional]</param>
/// <returns><see cref="WireMockServer"/></returns>
[PublicAPI]
public WireMockServer AddGraphQLSchema(string id, AnyOf<string, StringPattern> graphQLSchema, Dictionary<string, Type>? customScalars = null)
{
Guard.NotNullOrWhiteSpace(id);
Guard.NotNullOrWhiteSpace(graphQLSchema);
_settings.GraphQLSchemas ??= new Dictionary<string, GraphQLSchemaDetails>();
_settings.GraphQLSchemas[id] = new GraphQLSchemaDetails
{
SchemaAsString = graphQLSchema,
CustomScalars = customScalars
};
return this;
}
/// <inheritdoc />
[PublicAPI]
public string? MappingToCSharpCode(Guid guid, MappingConverterType converterType)