简体   繁体   中英

Cannot import google's proto with @grpc/proto-loader

I have the following proto:

syntax = "proto3";

import "google/rpc/status.proto";

message Response {   
    google.rpc.Status status = 1;
}

message Request {   
    Type name = 1;
}

service Service {
    rpc SomeMethod (Request) returns (Response);
}

And I am writing a client in node:

    const path = require('path');
    const grpc = require('grpc');
    const protoLoader = require('@grpc/proto-loader');
    const protoFiles = require('google-proto-files');

    const PROTO_PATH = path.join(__dirname, '/proto/myproto.proto');

    const packageDefinition = protoLoader.loadSync(
      PROTO_PATH,
      {
        keepCase: true,
        longs: String,
        enums: String,
        defaults: true,
        oneofs: true,
        includeDirs: [protoFiles('rpc')],
      },
    );

    const proto = grpc.loadPackageDefinition(packageDefinition);
    const client = new proto.Service('localhost:1111', grpc.credentials.createInsecure());

When I run the client, I get the following error: TypeError: proto.Service is not a constructor. I found it's related to the import of status.proto. What is the right way of importing google protos using proto-loader? The server is in Java.

Olga, you cannot use the absolute path in the PROTO_PATH if you are using includeDirs. Apparently you need to put both path, ie path to myproto.proto AND path to the google-proto-files into includeDirs and use just file name as PROTO_PATH then it works just fine. See here:

https://github.com/grpc/grpc-node/issues/470

Here is modified code that works. Please note that I also had to replace "Type" with "int32" in the myproto.proto.

const path = require('path');
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
const protoFiles = require('google-proto-files');

const PROTO_PATH = 'myproto.proto';

const packageDefinition = protoLoader.loadSync(
  PROTO_PATH,
  {
    keepCase: true,
    longs: String,
    enums: String,
    defaults: true,
    oneofs: true,
    includeDirs: ['node_modules/google-proto-files', 'proto']
    },
  );

const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const client = new protoDescriptor.Service('localhost:1111',  grpc.credentials.createInsecure());

Hope it helps. :)

The problem here is that the path that protoFiles('rpc') returns doesn't work with the import line in your .proto file. That import line means that @grpc/proto-loader is looking for an include directory that contains google/rpc/status.proto , but protoFiles('rpc') returns a directory that directly contains status.proto . So, you have to change one or both of those things so that the relative directories match up properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM