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,205 @@
#if PROTOBUF
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using FluentAssertions;
using Greet;
using Grpc.Net.Client;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using Xunit;
// ReSharper disable once CheckNamespace
namespace WireMock.Net.Tests;
public partial class WireMockServerTests
{
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;
}
";
[Theory]
[InlineData("CgRzdGVm")]
[InlineData("AAAAAAYKBHN0ZWY=")]
public async Task WireMockServer_WithBodyAsProtoBuf(string data)
{
// Arrange
var bytes = Convert.FromBase64String(data);
var jsonMatcher = new JsonMatcher(new { name = "stef" });
using var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc/greet.Greeter/SayHello")
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloRequest", jsonMatcher)
)
.RespondWith(Response.Create()
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloReply",
new
{
message = "hello"
}
)
.WithTrailingHeader("grpc-status", "0")
);
// Act
var protoBuf = new ByteArrayContent(bytes);
protoBuf.Headers.ContentType = new MediaTypeHeaderValue("application/grpc-web");
var client = server.CreateClient();
var response = await client.PostAsync("/grpc/greet.Greeter/SayHello", protoBuf);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
Convert.ToBase64String(responseBytes).Should().Be("AAAAAAcKBWhlbGxv");
server.Stop();
}
[Fact]
public async Task WireMockServer_WithBodyAsProtoBuf_InlineProtoDefinition_UsingGrpcGeneratedClient()
{
// Arrange
using var server = WireMockServer.Start(useHttp2: true);
var jsonMatcher = new JsonMatcher(new { name = "stef" });
server
.Given(Request.Create()
.UsingPost()
.WithPath("/greet.Greeter/SayHello")
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloRequest", jsonMatcher)
)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithTrailingHeader("grpc-status", "0")
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloReply",
new
{
message = "hello stef {{request.method}}"
}
)
.WithTransformer()
);
// Act
var channel = GrpcChannel.ForAddress(server.Url!);
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = "stef" });
// Assert
reply.Message.Should().Be("hello stef POST");
server.Stop();
}
[Fact]
public async Task WireMockServer_WithBodyAsProtoBuf_MappingProtoDefinition_UsingGrpcGeneratedClient()
{
// Arrange
using var server = WireMockServer.Start(useHttp2: true);
var jsonMatcher = new JsonMatcher(new { name = "stef" });
server
.Given(Request.Create()
.UsingPost()
.WithHttpVersion("2")
.WithPath("/greet.Greeter/SayHello")
.WithBodyAsProtoBuf("greet.HelloRequest", jsonMatcher)
)
.WithProtoDefinition(ProtoDefinition)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithTrailingHeader("grpc-status", "0")
.WithBodyAsProtoBuf("greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}} {{request.method}}"
}
)
.WithTransformer()
);
// Act
var channel = GrpcChannel.ForAddress(server.Url!);
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = "stef" });
// Assert
reply.Message.Should().Be("hello stef POST");
server.Stop();
}
[Fact]
public async Task WireMockServer_WithBodyAsProtoBuf_ServerProtoDefinition_UsingGrpcGeneratedClient()
{
// Arrange
var id = $"test-{Guid.NewGuid()}";
using var server = WireMockServer.Start(useHttp2: true);
var jsonMatcher = new JsonMatcher(new { name = "stef" });
server
.AddProtoDefinition(id, ProtoDefinition)
.Given(Request.Create()
.UsingPost()
.WithHttpVersion("2")
.WithPath("/greet.Greeter/SayHello")
.WithBodyAsProtoBuf("greet.HelloRequest", jsonMatcher)
)
.WithProtoDefinition(id)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithTrailingHeader("grpc-status", "0")
.WithBodyAsProtoBuf("greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}} {{request.method}}"
}
)
.WithTransformer()
);
// Act
var channel = GrpcChannel.ForAddress(server.Url!);
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = "stef" });
// Assert
reply.Message.Should().Be("hello stef POST");
server.Stop();
}
}
#endif

View File

@@ -0,0 +1,33 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}