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

@@ -0,0 +1,128 @@
#if !(NET452 || NET461 || NETCOREAPP3_1)
using System.Threading.Tasks;
using RestEase;
using VerifyXunit;
using WireMock.Client;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using Xunit;
namespace WireMock.Net.Tests.AdminApi;
public partial class WireMockAdminApiTests
{
private const string ProtoDefinition = @"
syntax = ""proto3"";
package greet;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
";
[Fact]
public async Task IWireMockAdminApi_GetMappingsAsync_WithBodyAsProtoBuf_ShouldReturnCorrectMappingModels()
{
// Arrange
using var server = WireMockServer.StartWithAdminInterface();
var protoBufJsonMatcher = new JsonPartialWildcardMatcher(new { name = "*" });
server
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc/greet.Greeter/SayHello")
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloRequest", protoBufJsonMatcher)
)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}}"
}
)
.WithTrailingHeader("grpc-status", "0")
.WithTransformer()
);
server
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc2/greet.Greeter/SayHello")
.WithBodyAsProtoBuf("greet.HelloRequest", protoBufJsonMatcher)
)
.WithProtoDefinition(ProtoDefinition)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithBodyAsProtoBuf("greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}}"
}
)
.WithTrailingHeader("grpc-status", "0")
.WithTransformer()
);
server
.AddProtoDefinition("my-greeter", ProtoDefinition)
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc3/greet.Greeter/SayHello")
.WithBodyAsProtoBuf("greet.HelloRequest", protoBufJsonMatcher)
)
.WithProtoDefinition("my-greeter")
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithBodyAsProtoBuf("greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}}"
}
)
.WithTrailingHeader("grpc-status", "0")
.WithTransformer()
);
server
.AddProtoDefinition("my-greeter", ProtoDefinition)
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc4/greet.Greeter/SayHello")
.WithBodyAsProtoBuf("greet.HelloRequest")
)
.WithProtoDefinition("my-greeter")
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithBodyAsProtoBuf("greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}}"
}
)
.WithTrailingHeader("grpc-status", "0")
.WithTransformer()
);
// Act
var api = RestClient.For<IWireMockAdminApi>(server.Url);
var getMappingsResult = await api.GetMappingsAsync().ConfigureAwait(false);
await Verifier.Verify(getMappingsResult, VerifySettings);
server.Stop();
}
}
#endif

View File

@@ -0,0 +1,25 @@
{
Guid: 90356dba-b36c-469a-a17e-669cd84f1f05,
UpdatedAt: DateTime_1,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /1,
IgnoreCase: false
}
]
},
Body: {
Matcher: {
Name: RegexMatcher,
Pattern: hello,
IgnoreCase: true
}
}
},
Response: {
Body: world
}
}

View File

@@ -0,0 +1,30 @@
{
Guid: 90356dba-b36c-469a-a17e-669cd84f1f05,
UpdatedAt: DateTime_1,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /1,
IgnoreCase: false
}
]
},
Body: {
Matcher: {
Name: RegexMatcher,
Pattern: hello,
IgnoreCase: true
}
}
},
Response: {
ProxyUrl: https://my-proxy.com,
ProxyUrlReplaceSettings: {
OldValue: x,
NewValue: y,
IgnoreCase: true
}
}
}

View File

@@ -0,0 +1,35 @@
{
Guid: 90356dba-b36c-469a-a17e-669cd84f1f05,
UpdatedAt: DateTime_1,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /foo1,
IgnoreCase: false
}
]
},
Methods: [
GET
],
Params: [
{
Name: p1,
Matchers: [
{
Name: ExactMatcher,
Pattern: xyz,
IgnoreCase: false
}
]
}
]
},
Response: {
StatusCode: 200,
BodyDestination: SameAsSource,
Body: 1
}
}

View File

@@ -0,0 +1,12 @@
var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingMethod("GET")
.WithPath("/foo1")
.WithParam("p1", "xyz")
)
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody("1")
);

View File

@@ -0,0 +1,235 @@
[
{
Guid: Guid_1,
UpdatedAt: DateTime_1,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /grpc/greet.Greeter/SayHello,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: ProtoBufMatcher,
Pattern:
syntax = "proto3";
package greet;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
,
ContentMatcher: {
Name: JsonPartialWildcardMatcher,
Pattern: {
name: *
},
IgnoreCase: false,
Regex: false
},
ProtoBufMessageType: greet.HelloRequest
}
}
},
Response: {
BodyAsJson: {
message: hello {{request.BodyAsJson.name}}
},
UseTransformer: true,
TransformerType: Handlebars,
TransformerReplaceNodeOptions: EvaluateAndTryToConvert,
Headers: {
Content-Type: application/grpc
},
TrailingHeaders: {
grpc-status: 0
},
ProtoDefinition:
syntax = "proto3";
package greet;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
,
ProtoBufMessageType: greet.HelloReply
}
},
{
Guid: Guid_2,
UpdatedAt: DateTime_2,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /grpc2/greet.Greeter/SayHello,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: ProtoBufMatcher,
ContentMatcher: {
Name: JsonPartialWildcardMatcher,
Pattern: {
name: *
},
IgnoreCase: false,
Regex: false
},
ProtoBufMessageType: greet.HelloRequest
}
}
},
Response: {
BodyAsJson: {
message: hello {{request.BodyAsJson.name}}
},
UseTransformer: true,
TransformerType: Handlebars,
TransformerReplaceNodeOptions: EvaluateAndTryToConvert,
Headers: {
Content-Type: application/grpc
},
TrailingHeaders: {
grpc-status: 0
},
ProtoBufMessageType: greet.HelloReply
},
ProtoDefinition:
syntax = "proto3";
package greet;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
},
{
Guid: Guid_3,
UpdatedAt: DateTime_3,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /grpc3/greet.Greeter/SayHello,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: ProtoBufMatcher,
ContentMatcher: {
Name: JsonPartialWildcardMatcher,
Pattern: {
name: *
},
IgnoreCase: false,
Regex: false
},
ProtoBufMessageType: greet.HelloRequest
}
}
},
Response: {
BodyAsJson: {
message: hello {{request.BodyAsJson.name}}
},
UseTransformer: true,
TransformerType: Handlebars,
TransformerReplaceNodeOptions: EvaluateAndTryToConvert,
Headers: {
Content-Type: application/grpc
},
TrailingHeaders: {
grpc-status: 0
},
ProtoBufMessageType: greet.HelloReply
},
ProtoDefinition: my-greeter
},
{
Guid: Guid_4,
UpdatedAt: DateTime_4,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /grpc4/greet.Greeter/SayHello,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: ProtoBufMatcher,
ProtoBufMessageType: greet.HelloRequest
}
}
},
Response: {
BodyAsJson: {
message: hello {{request.BodyAsJson.name}}
},
UseTransformer: true,
TransformerType: Handlebars,
TransformerReplaceNodeOptions: EvaluateAndTryToConvert,
Headers: {
Content-Type: application/grpc
},
TrailingHeaders: {
grpc-status: 0
},
ProtoBufMessageType: greet.HelloReply
},
ProtoDefinition: my-greeter
}
]

View File

@@ -0,0 +1,89 @@
var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingMethod("GET")
.WithPath("/foo1")
.WithParam("p1", "xyz")
)
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody("1")
);
server
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/foo2")
.WithParam("p2", "abc")
.WithHeader("h1", "W/\"234f2q3r\"", true)
)
.WithGuid("1b731398-4a5b-457f-a6e3-d65e541c428f")
.RespondWith(Response.Create()
.WithStatusCode("201")
.WithHeader("hk", "hv")
.WithHeader("ETag", "W/\"168d8e\"")
.WithBody("2")
);
server
.Given(Request.Create()
.UsingMethod("DELETE")
.WithUrl("https://localhost/test")
)
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
.RespondWith(Response.Create()
.WithStatusCode(208)
.WithBodyAsJson(new
{
@as = 1,
b = 1.2,
d = true,
e = false,
f = new [] { 1, 2, 3, 4 },
g = new
{
z1 = 1,
z2 = 2,
z3 = new [] { "a", "b", "c" },
z4 = new []
{
new
{
a = 1,
b = 2
},
new
{
a = 2,
b = 3
}
}
},
date_field = "2023-05-08T11:20:19",
string_field_with_date = "2021-03-13T21:04:00Z",
multiline_text = @"This
is
multiline
text
"
})
);
server
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/foo3")
.WithBody(new JsonPartialMatcher(
value: "{ a = 1, b = 2 }",
ignoreCase: false,
regex: false
))
)
.WithGuid("4126dec8-470b-4eff-93bb-c24f83b8b1fd")
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody(@"Line1
Some ""value"" in Line2")
);

File diff suppressed because it is too large Load Diff