Skip to content
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

Add gRPC JSON transcoding #40242

Merged
merged 11 commits into from
Mar 27, 2022
Merged

Add gRPC JSON transcoding #40242

merged 11 commits into from
Mar 27, 2022

Conversation

JamesNK
Copy link
Member

@JamesNK JamesNK commented Feb 15, 2022

Moving code from https://github.com/aspnet/AspLabs/tree/main/src/GrpcHttpApi

  • Unit and integration tests - Not worth the time to review
  • Microsoft.AspNetCore.Grpc.HttpApi - main project
    • / - public API
    • /Internal/Binding - code related to discovering and binding grpc methods as RESTful endpoints
    • /Internal/CallHandlers - entry code when executing gRPC JSON transcoding
    • /Internal/Json - code for System.Text.Json to convert from protobuf to JSON. See https://developers.google.com/protocol-buffers/docs/proto3#json. Ignore Legacy.cs. Copied from Google.Protobuf and will be replaced
    • /Internal - various helper methods. Also has callcontext and streamwriter which are used when executing gRPC methods as RESTful endpoints
  • Microsoft.AspNetCore.Grpc.Swagger - swashbuckle integration. Populates ApiDescriptionProvider, as well as customizing how swashbuckle generates schemas for protobuf types and swagger documentation from generated XML
    • / - public API
    • /Internal/XmlComments - custom swagger documentation from generated XML
    • /Internal - everything else

@JamesNK JamesNK requested review from dougbu, a team and Pilchie as code owners February 15, 2022 08:34
@Pilchie Pilchie added the area-grpc Includes: GRPC wire-up, templates label Feb 15, 2022

if (serverCallContext.Status.StatusCode != StatusCode.OK)
{
throw new RpcException(serverCallContext.Status);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a message that can be provided here?

@dougbu dougbu self-assigned this Feb 23, 2022
@dougbu dougbu mentioned this pull request Feb 23, 2022
Copy link
Member

@dougbu dougbu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wtgodbe please double-check the msbuild goop I added. It's pretty much as we discussed -- I think.

src/BuildAfterApp/BuildAfterApp.csproj Outdated Show resolved Hide resolved
Comment on lines 11 to 13
<!-- Workaround lack of Linux MUSL x64 support. -->
<ExcludeFromBuild
Condition=" '$(TargetOsName)' == 'linux-musl' and '$(TargetArchitecture)' == 'x64' ">true</ExcludeFromBuild>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JamesNK I'm not sure of the bug here but the tooling fails to start on Linux MUSL x64.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grpc.Tools has some native components. Might not support architecture?

Do the gRPC integration tests have the same issue? They also use Grpc.Tools.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean by "gRPC integration tests". If that's InteropTests, then no, they're fine because we don't run or build tests on Linux MUSL x64. Hit the problem here because the folder includes implementation projects and I hadn't got the exclusions in BuildAfterApp.csproj working right. (Yeah, I discovered a problem because something else was busted 😺)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put another way, I left this here as defence-in-depth and a reminder.

{
if (reader.TokenType == JsonTokenType.String)
{
return long.Parse(reader.GetString()!, CultureInfo.InvariantCulture);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is support for string numbers really needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a rule in gRPC <-> JSON transcoding. 64 bits don't fit into a JavaScript's 50ish bit number. So send as a string instead.

Not a fan but need to support it.

Copy link
Member

@wtgodbe wtgodbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSBuild goop looks good, other than the name of the .csproj

@dougbu
Copy link
Member

dougbu commented Mar 2, 2022

@JamesNK I rebased on 'main' to handle the AspNetCore.sln conflicts. Will address @wtgodbe's renaming suggestion later today or tomorrow.

Copy link
Member

@captainsafia captainsafia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM YOLO

@@ -50,9 +47,10 @@ public override async Task StreamingOutputCall(StreamingOutputCallRequest reques

foreach (var responseParam in request.ResponseParameters)
{
// TODO(JamesNK): Remove nullable override after Grpc.Core.Api update
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this now after the 2.40.0 -> 2.43.0 updates in Version.props?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it requires 2.45.0

else
{
// Consider setting to enable mapping to methods without HttpRule
// AddMethodCore(method, method.FullName, "GET", string.Empty, string.Empty, methodDescriptor);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a log when an HttpRule is not found similar to when a MethodDescriptor is not found?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's normal to have a gRPC method that you don't want a RESTful version for. They don't have a HttpRule defined on them by the user.

if (response == null)
{
// This is consistent with Grpc.Core when a null value is returned
throw new RpcException(new Status(StatusCode.Cancelled, "No message returned from method."));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, did we ever come to a conclusion about grpc/grpc-dotnet#1555?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Next 1:1 with Jan I'll bring it up again.

{
if (includeExceptionDetails ?? false)
{
return message + " " + CommonGrpcProtocolHelpers.ConvertToRpcExceptionMessage(exception);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with exception.ToString()? Are we trying to avoid stack traces?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

{
throw new InvalidOperationException("Expected string value for FieldMask.");
}
// TODO: Do we *want* to remove empty entries? Probably okay to treat "" as "no paths", but "foo,,bar"?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we didn't remove empty entries, "" would give a single path and "," would give two? I think removing empty entries probably makes sense, but I don't know the spec.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field mask logic matches what is in the Google.Protobuf serializer. I'll add to the todo that we should follow their lead.


public override void Write(Utf8JsonWriter writer, TMessage value, JsonSerializerOptions options)
{
var paths = (IList<string>)value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove empty entries from paths then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field mask logic matches what is in the Google.Protobuf serializer. I'll add to the todo that we should follow their lead.


public IDisposable BeginScope<TState>(TState state)
{
return null!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soon we won't need this !! dotnet/runtime#66960

@JamesNK
Copy link
Member Author

JamesNK commented Mar 26, 2022

@dougbu There is a project - Microsoft.AspNetCore.Grpc.Swagger - in this PR that isn't ready yet to be published. It will hopefully be ready in a couple of previews.

I set IsPackable and IsShipping to false. Is that the right way to exclude it?

@dougbu
Copy link
Member

dougbu commented Mar 26, 2022

I set IsPackable and IsShipping to false. Is that the right way to exclude it?

Either works. $(IsPackable) controls whether the build creates a .nupkg at all and $(IsShipping) controls package versioning -- non-shipping packages are created but automatically not included in a release.

@JamesNK JamesNK merged commit b4b43e3 into main Mar 27, 2022
@JamesNK JamesNK deleted the jamesnk/grpctranscoding branch March 27, 2022 12:29
@ghost ghost added this to the 7.0-preview3 milestone Mar 27, 2022
@dougbu dougbu modified the milestones: 7.0-preview3, 7.0-preview4 Apr 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-grpc Includes: GRPC wire-up, templates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants