-
-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using google.protobuf.Empty as response results in a bad gRPC response #1144
Comments
@ArcaneTSGK Thanks for noticing this. This is a new scenario I never tested. I'll keep you informed on the progress... |
@ArcaneTSGK And what should actually be the behavior of WireMock.Net if a google.protobuf.Empty is a return value? |
@StefH There are a number of them yes, For Empty return value it's Converting Empty to JSON would represent an empty JSON object {} Here are all of Googles Well Known types: https://protobuf.dev/reference/protobuf/google.protobuf/ https://protobuf.dev/reference/protobuf/google.protobuf/#empty Returning any of the scalar types in protobuf within a custom response that maps to a C# type is fine except for 'Enum'. I've not tried the 'Any' well-known type as my application doesn't have use for it, but I imagine that one might cause some issues, also when working with nullable types you use 'OneOf', again I haven't had to use these so I do not know if they'll work, but this is what a proto file would look like using those: Usage of 'Any' syntax = "proto3";
package tutorial;
import "include/google/protobuf/any.proto"
message Animal {
string name=1;
int32 age=2;
google.protobuf.Any care_giver=3;
}
message Owner {
int32 id=1;
string first_name=2;
string last_name=3;
}
message Foster {
int32 id=1;
string address=2;
} In that example a care give can be any pre-defined message in the proto, which could be Owner or the Foster, so that might be a test case for Wiremock to see if Any maps back, and lastly OneOf for nullables where you'd need to be able to allow a null return in the response: And this is OneOf import "google/protobuf/struct.proto";
package tutorial;
option csharp_namespace = "MyExample.Dog";
message Dog {
google.protobuf.Int32Value id=1;
string name=2;
NullableField profile_picture=3;
}
message NullableField {
oneof kind {
google.protobuf.NullValue null=1;
google.protobuf.StringValue value=2;
}
} |
Currently I only have an easy way to support:
|
@ArcaneTSGK |
@ArcaneTSGK
|
I will have some time tomorrow to take a look, I'll let you know my results, thanks @StefH |
@ArcaneTSGK |
@ArcaneTSGK |
Hi @StefH sorry for the delay, Unfortunately, I can't install your prerelease version 1.5.62-ci-19067 as it does not resolve, are your pre-releases publicly available? I only have the option (with prereleases enabled) to install 1.5.62 or 1.60 / 1.61 |
Preview versions are defined on MyGet. But it could be that that specific version is automatically deleted because only x versions are kept on MyGet. I will take a look and maybe I need to build a new preview. |
No worries, I've added MyGet as a feed and will await the specific version with the gRPC fix to test |
@ArcaneTSGK |
So I attempted to use this build and I get the following exception: (Status(StatusCode="Internal", Detail="Failed to deserialize response message.") The proto file looks like this
The test is setup as follows:
I did try Duration and Timestamp aswell but those were returning unimplemented for me when I was using Let me know if I'm missing anything I also tried the fully qualified name of Google.Protobuf.WellKnownTypes.Empty as the message type to no avail. Thanks |
Strange, I did add a unit test https://github.com/WireMock-Net/WireMock.Net/blob/bug/1144-protobuf/test/WireMock.Net.Tests/Grpc/WireMockServerTests.Grpc.cs#L104 proto private const string ProtoDefinitionWithWellKnownTypes = @"
syntax = ""proto3"";
import ""google/protobuf/empty.proto"";
import ""google/protobuf/timestamp.proto"";
import ""google/protobuf/duration.proto"";
service Greeter {
rpc SayNothing (google.protobuf.Empty) returns (google.protobuf.Empty);
}
message MyMessageTimestamp {
google.protobuf.Timestamp ts = 1;
}
message MyMessageDuration {
google.protobuf.Duration du = 1;
}
"; Unit test code: // Arrange
var bytes = Convert.FromBase64String("CgRzdGVm");
using var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingPost()
.WithPath("/grpc/Greeter/SayNothing")
.WithBody(new NotNullOrEmptyMatcher())
)
.RespondWith(Response.Create()
.WithBodyAsProtoBuf(ProtoDefinitionWithWellKnownTypes, "google.protobuf.Empty",
new { }
)
.WithTrailingHeader("grpc-status", "0")
.WithTransformer()
);
// Act
var protoBuf = new ByteArrayContent(bytes);
protoBuf.Headers.ContentType = new MediaTypeHeaderValue("application/grpc-web");
var client = server.CreateClient();
var response = await client.PostAsync("/grpc/Greeter/SayNothing", protoBuf);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
Convert.ToBase64String(responseBytes).Should().Be("");
server.Stop(); What is the difference? |
I will have to provide a minimal reproduction solution when I have time, I've tried a few different things and for .Empty I always get the unable to deserialize response, and for duration/timestamp I'm getting the Unimplemented error. I'll provide a link to the repository and throw something together by the end of the week |
Using https://protobuf.heyenrath.nl/ with your message and |
Hello @ArcaneTSGK, could you make an example project to demonstrate this issue? |
1 similar comment
Hello @ArcaneTSGK, could you make an example project to demonstrate this issue? |
Hello,
|
@carlos-pilao-deltatre |
@StefH
|
You did check MyGet? |
yes |
try this |
When writing a response builder with
google.protobuf.Empty
the mock gRPC client will returnStatusCode=Unimplemented
.Expected behavior:
It should be possible to use googles 'WellKnown' types as the protobuf body in the response builder.
Test to reproduce
I have tried with and without the
.WithTransformer()
, I have also tried withnew Empty()
new Empty {}
andnew()
but none of those match.Other related info
I am able to get the tests to work if the response is a type that I create in my proto, for example lets say that the HelloReply is in the proto file with a
message HelloReply { string reply_message = 1; }
I have also tried creating my own
message EmptyResponse { }
and this also did not workIt only works when the response contains something like
I have also tried creating my own
message EmptyResponse { string status = 1; }
Please can someone either point me in the direction of what I am doing wrong to match an empty response, or confirm that this is a bug
Thanks
The text was updated successfully, but these errors were encountered: