grpc-node icon indicating copy to clipboard operation
grpc-node copied to clipboard

Usage of custom options

Open tscpp opened this issue 4 years ago • 10 comments

Problem description

How do I get defined custom options from messages and services? The messages and service objects from output has options properties, but it is always null.

Reproduction steps

  1. Run npm init -y in a new directory
  2. Run npm install @grpc/[email protected]
  3. main.js
    const proto = require('@grpc/proto-loader')
    const util = require('util')
    
    const definition = proto.loadSync('main.proto')
    console.log('MyService: ', util.inspect(definition.MyService, false, 1000, true))
    console.log('MyMessage: ', util.inspect(definition.MyMessage, false, 1000, true))
    
  4. main.proto
    syntax = "proto3";
    import "google/protobuf/descriptor.proto";
    
    extend google.protobuf.MessageOptions {
        string my_option = 51234;
    }
    
    service MyService {
    	rpc MyRpc(MyMessage) returns (MyMessage) {
    		option (my_option) = "Hello world!";
    	}
    }
    
    message MyMessage {
        option (my_option) = "Hello world!";
    }
    
  5. Run node main.js
  6. The output doesn't contain any info about custom options.

Environment

  • OS name, version and architecture: [Windows 10 64x 20H2]
  • Node version [v14.16.1]
  • Node installation method [website]
  • If applicable, compiler version []
  • Package name and version [@grpc/[email protected]]

Additional context

@grpc/grpc-js does not add any additional data about custom options.

Console output: https://gist.githubusercontent.com/tscpp/32f889a1989b8f86e6a91af507438b53/raw/6973cab8d80dafcd2a94eff3ace1305ae133fd86/log.txt

tscpp avatar May 03 '21 13:05 tscpp

You are correct, @grpc/proto-loader does not currently output information about custom options.

murgatroid99 avatar May 04 '21 20:05 murgatroid99

Is there any progress on this feature request? Would be great to see it on the next Roadmap. Thanks

desytech avatar Dec 31 '21 21:12 desytech

@murgatroid99 Is it possible to upvote custom message options? Thanks

desytech avatar Apr 23 '22 22:04 desytech

Are there any news to access custom service and method options via @grpc/proto-loader? Is this feature available in new protobufjs (7.xx) versions? @desytech: Do you have you found any workarounds to access options in node?

the-duke avatar Feb 14 '23 10:02 the-duke

I also would like to access custom options from a package definition returned by protoLoader.load. It seems like the current protobufjs version 7.x. already supports parsing (custom) options from proto files. Thus the protobufjs objects passed to proto-loader's functions like createMethodDefinition or createServiceDefinition already have those options. So I think the only thing that needs to be done is to add the options to the returned definitions.

The following patch works for me (@grpc/proto-loader 0.7.10 - only tested with custom method options):

diff --git a/node_modules/@grpc/proto-loader/build/src/index.js b/node_modules/@grpc/proto-loader/build/src/index.js
index 5bbf6b3..1f5da21 100644
--- a/node_modules/@grpc/proto-loader/build/src/index.js
+++ b/node_modules/@grpc/proto-loader/build/src/index.js
@@ -99,10 +99,13 @@ function createMethodDefinition(method, serviceName, options, fileDescriptors) {
         originalName: camelCase(method.name),
         requestType: createMessageDefinition(requestType, fileDescriptors),
         responseType: createMessageDefinition(responseType, fileDescriptors),
+        _options: method.options || {},
     };
 }
 function createServiceDefinition(service, name, options, fileDescriptors) {
-    const def = {};
+    const def = {
+        _options: service.options || {},
+    };
     for (const method of service.methodsArray) {
         def[method.name] = createMethodDefinition(method, name, options, fileDescriptors);
     }
@@ -114,6 +117,7 @@ function createMessageDefinition(message, fileDescriptors) {
         format: 'Protocol Buffer 3 DescriptorProto',
         type: messageDescriptor.$type.toObject(messageDescriptor, descriptorOptions),
         fileDescriptorProtos: fileDescriptors,
+        _options: message.options || {},
     };
 }
 function createEnumDefinition(enumType, fileDescriptors) {
@@ -122,6 +126,7 @@ function createEnumDefinition(enumType, fileDescriptors) {
         format: 'Protocol Buffer 3 EnumDescriptorProto',
         type: enumDescriptor.$type.toObject(enumDescriptor, descriptorOptions),
         fileDescriptorProtos: fileDescriptors,
+        _options: enumType.options || {},
     };
 }
 /**

@murgatroid99, is it really that simple or did I miss something? Would you accept a PR for this?

n0v1 avatar Feb 19 '24 14:02 n0v1

@n0v1 The main problem is the types. I suggest looking at #2230, and the comments in particular, for a previous attempt at this. In short, the type of the options field from Protobuf.js is actually fairly complicated, and it has a lot of ambiguity that we can avoid here. I would only want to include the options if we can define the types as narrowly as possible.

murgatroid99 avatar Feb 20 '24 18:02 murgatroid99

Thanks for pointing at the existing pull request. Let's continue the discussion there. I might find some time to work on this.

n0v1 avatar Feb 21 '24 07:02 n0v1