Git Product home page Git Product logo

grpc-curl's Introduction

grpc-curl Build Status Coverage Status NuGet

grpc-curl is a command line tool for interacting with gRPC servers.

All the functionalities of grpc-curl are also accessible through the NuGet package DynamicGrpc that is part of this repository.

This tool is the .NET equivalent of the popular gRPCurl written in Golang.

NOTE: grpc-curl doesn't not support yet all the features that gRPCurl is providing.

Features

  • Allows to invoke method services for all gRPC calling modes (unary, client streaming, server streaming, full-duplex).
  • Allows to print proto reflection descriptors back to proto language (via --describe with grpc-curl, or via the API .ToProtoString() with DynamicGrpc)
  • Supports for plain Protocol Buffers naming conventions and JSON.
  • Supports for google.protobuf.Any: The type has to be encoded - and is decoded with the shadow property @type on a dictionary (e.g @type = "type.googleapis.com/YourTypeName").
  • Build on top of the DynamicGrpc library available as a separate NuGet package.
  • Build for net6.0+
  • Available for multiple platforms. See binaries section below.

Usage

grpc-curl currently requires that the gRPC server has activated gRPC reflection.

Copyright (C) 2022 Alexandre Mutel. All Rights Reserved
grpc-curl - Version: 1.3.6

Usage: grpc-curl [options] address service/method

  address: A http/https URL or a simple host:address.
           If only host:address is used, HTTPS is used by default
           unless the options --http is passed.

## Options

  -d, --data=VALUE           Data for string content.
      --http                 Use HTTP instead of HTTPS unless the protocol is
                               specified directly on the address.
      --json                 Use JSON naming for input and output.
      --describe             Describe the service or dump all services
                               available.
  -v, --verbosity[=VALUE]    Set verbosity.
  -h, --help                 Show this help.

Query a service

./grpc-curl --json -d "{""getStatus"":{}}" http://192.168.100.1:9200 SpaceX.API.Device.Device/Handle

Will print the following result:

{
  "apiVersion": 4,
  "dishGetStatus": {
    "deviceInfo": {
      "id": "0000000000-00000000-00000000",
      "hardwareVersion": "rev2_proto3",
      "softwareVersion": "992cafb5-61c7-46a3-9ef7-5907c8cf90fd.uterm.release",
      "countryCode": "FR",
      "utcOffsetS": 1
    },
    "deviceState": {
      "uptimeS": 667397
    },
    "obstructionStats": {
      "fractionObstructed": 2.2786187E-06,
      "wedgeFractionObstructed": [
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0
      ],
      "wedgeAbsFractionObstructed": [
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0
      ],
      "validS": 667070.0,
      "avgProlongedObstructionIntervalS": "NaN"
    },
    "alerts": {
      "roaming": true
    },
    "downlinkThroughputBps": 461012.72,
    "uplinkThroughputBps": 294406.6,
    "popPingLatencyMs": 30.35,
    "boresightAzimuthDeg": 0.7464048,
    "boresightElevationDeg": 65.841354,
    "gpsStats": {
      "gpsValid": true,
      "gpsSats": 12
    }
  }
}

Describe a service

./grpc-curl --describe http://192.168.100.1:9200 SpaceX.API.Device.Device

Will print:

// SpaceX.API.Device.Device is a service:
service Device {
  rpc Stream ( .SpaceX.API.Device.ToDevice ) returns ( .SpaceX.API.Device.FromDevice );
  rpc Handle ( .SpaceX.API.Device.Request ) returns ( .SpaceX.API.Device.Response );
}

Describe all proto files serviced via reflection

./grpc-curl --describe http://192.168.100.1:9200

Will print:

// spacex/api/common/status/status.proto is a proto file.
syntax = "proto3";

package SpaceX.API.Status;

// SpaceX.API.Status.Status is a message:
message Status {
  int32 code = 1;
  string message = 2;
}


// spacex/api/device/command.proto is a proto file.
syntax = "proto3";

package SpaceX.API.Device;

// SpaceX.API.Device.PublicKey is a message:
message PublicKey {
  string key = 1;
  repeated Capability capabilities = 2;
}

// ....... and more prints ........

Usage API

All the functionalities of grpc-curl are also accessible through the NuGet package DynamicGrpc.

var channel = GrpcChannel.ForAddress("http://192.168.100.1:9200");
// Fetch reflection data from server
var client = await DynamicGrpcClient.FromServerReflection(channel);

// Call the method `Handle` on the service `SpaceX.API.Device.Device`
var result = await client.AsyncUnaryCall("SpaceX.API.Device.Device", "Handle", new Dictionary<string, object>()
{
    { "get_status", new Dictionary<string, object>() }
});

// Print a proto descriptor
FileDescriptor descriptor = client.Files[0];
Console.WriteLine(descriptor.ToProtoString());

Binaries

grpc-curl is available on multiple platforms:

Platform Packages
win-x64, win-arm, win-arm64 zip
linux-x64, linux-arm, linux-arm64 deb, tar
rhel-x64 rpm, tar
osx-x64, osx-arm64 tar

If you have dotnet 6.0 installed, you can install this tool via NuGet:

dotnet tool install --global grpc-curl

Otherwise, you can install native binaries to Windows, Linux, and macOS with the various debian/rpm/zip packages available directly from the releases.

grpc-curl is also available via homebrew for macOS and Linux:

$ brew tap xoofx/grpc-curl
$ brew install grpc-curl

License

This software is released under the BSD-Clause 2 license.

Author

Alexandre Mutel aka xoofx.

grpc-curl's People

Contributors

atifaziz avatar xoofx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

grpc-curl's Issues

The `--describe` flag should not require the `--data` option

In the “Describe a service” section of the README, trying the given example:

./grpc-curl --describe http://192.168.100.1:9200 SpaceX.API.Device.Device

gives the following error:

Unexpected error GrpcCurl.GrpcCurlApp+GrpcCurlException: Failing to deserialize JSON data. Reason: Value cannot be null. (Parameter 'json').
   at GrpcCurl.GrpcCurlApp.ParseJson(String data) in A:\grpc-curl\main\src\GrpcCurl\GrpcCurlApp.cs:line 216
   at GrpcCurl.GrpcCurlApp.<>c__DisplayClass0_0.<<Run>b__0>d.MoveNext() in A:\grpc-curl\main\src\GrpcCurl\GrpcCurlApp.cs:line 42
--- End of stack trace from previous location ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at GrpcCurl.GrpcCurlApp.Run(String[] args) in A:\grpc-curl\main\src\GrpcCurl\GrpcCurlApp.cs:line 63

Issues with MapField type

Following the documentation here, I added support for the MapField type on a gPRC endpoint.

Using the Dynamic GRPC Nuget package, the MapField type is not supported. I assume the CLI has the same limitation due to the code being used is the same / very close to the same:

Source

await foreach (var result in client.AsyncDynamicCall(service, method, ToAsync(input)))
{
    jsonResponse = ToJson(result)!.ToJsonString();
}

Example

message Equipment {
	string Id = 1;
	string name = 2;
	EquipmentModel model = 3;

	repeated Attributes fields = 4;
}

message Attributes {
	map<string, string> values = 1;
}

Expected

The client should send the request.

Actual

The below error is thrown:

Status(StatusCode="Internal", Detail="Error starting gRPC call. KeyNotFoundException: The given key 'hull_color' was not present in the dictionary.", DebugException="System.Collections.Generic.KeyNotFoundException: The given key 'hull_color' was not present in the dictionary.
   at DynamicGrpc.DynamicMessageSerializer.ComputeSize(IDictionary`2 value, DynamicGrpcClientContext context)
   at DynamicGrpc.DynamicMessageSerializer.DynamicMessage.CalculateSize()
   at Google.Protobuf.CodedOutputStream.ComputeMessageSize(IMessage value)
   at Google.Protobuf.FieldCodec.<>c__32`1.<ForMessage>b__32_4(T message)
   at Google.Protobuf.Collections.RepeatedField`1.CalculateSize(FieldCodec`1 codec)
   at DynamicGrpc.DynamicMessageSerializer.ComputeFieldSize(UInt32 tag, MessageDescriptor parentDescriptor, FieldDescriptor fieldDescriptor, String key, Object value, DynamicGrpcClientContext context)
   at DynamicGrpc.DynamicMessageSerializer.ComputeSize(IDictionary`2 value, DynamicGrpcClientContext context)
   at DynamicGrpc.DynamicMessageSerializer.WriteFieldValue(UInt32 tag, MessageDescriptor parentDescriptor, FieldDescriptor fieldDescriptor, String keyName, Object value, WriteContext& output, DynamicGrpcClientContext context)
   at DynamicGrpc.DynamicMessageSerializer.WriteTo(IDictionary`2 value, WriteContext& output, DynamicGrpcClientContext context)
   at Google.Protobuf.MessageExtensions.WriteTo(IMessage message, IBufferWriter`1 output)
   at DynamicGrpc.DynamicMessageSerializer.<>c__DisplayClass11_0.<GetMarshaller>b__2(IDictionary`2 value, SerializationContext ctx)
   at Grpc.Net.Client.StreamExtensions.WriteMessageAsync[TMessage](Stream stream, GrpcCall call, TMessage message, Action`2 serializer, CallOptions callOptions)
   at Grpc.Net.Client.Internal.PushUnaryContent`2.WriteMessageCore(ValueTask writeMessageTask)
   at System.Net.Http.Http2Connection.Http2Stream.SendRequestBodyAsync(CancellationToken cancellationToken)
   at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at Grpc.Net.Client.Internal.GrpcCall`2.RunCall(HttpRequestMessage request, Nullable`1 timeout)")

Example Request

{
    "equipment": {
        "name": "test equipment",
        "fields": [
            {
                "hull_color": "white"
            },
            {
                "beam": "29"
            }
        ]
    }
}

Add support for default values

The server will not serialize properties that have their default values (e.g int32 = 0 won't be serialized).

The deserializer needs to add non optional (and required) property values that are default.

I have a similar idea about gRPC debuging and documents.

As you see, I have a similar idea to improve debuging and documents of gRPC. What I have done is to generate many dynamic routes so that I can call a gRPC API like a JSON API. I also extend SwaggerGen to make sure that every interface can be shown in SwaggerUI. Here are the link of my project:

https://github.com/qinyuanpei/FluentGrpc.Gateway

At the beginning,I generate description information for all interfaces based on assembly and reflection. Now I have a target to generate these information by gRPC ServerReflection. So I am very interested in your project. Thank you!

Is this project under active development / maintenance?

Hi there. I like what I can see in this project and was wondering if it is under active development / maintenance?

I'm looking to build something with support for dynamically serializing/deserializing Protocol Buffer messages based on Reflected or runtime Descriptor data. I've noticed that all the necessary classes in your project here are currently internal and was wondering if you were open to collaborating with me to evolve the DynamicGrpc library in a direction that would enable me to do this (i.e. without necessarily calling a Dynamic Grpc Client call)?

Thanks for your time. 😄

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.