Невозможно импортировать протокол Google с помощью @ grpc / proto-loader

У меня такой прото:

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);
}

И я пишу клиента в узле:

    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());

Когда я запускаю клиент, я получаю следующую ошибку: TypeError: proto.Service не является конструктором. Я обнаружил, что это связано с импортом status.proto. Как правильно импортировать протоколы Google с помощью прото-загрузчика? Сервер находится на Java.


person Olga    schedule 12.10.2018    source источник


Ответы (2)


Ольга, вы не можете использовать абсолютный путь в PROTO_PATH, если используете includeDirs. По-видимому, вам нужно поместить оба пути, то есть путь к myproto.proto И путь к файлам google-proto в includeDirs и использовать только имя файла как PROTO_PATH, тогда он работает нормально. Посмотреть здесь:

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

Вот модифицированный код, который работает. Обратите внимание, что мне также пришлось заменить «Тип» на «int32» в 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());

Надеюсь, это поможет. :)

person Maxim Sobolev    schedule 16.10.2018
comment
Работает с абсолютными путями: const IMPORT_PATH = path.join (__ dirname, '/ proto'); const GOOGLE_PROTOS = path.join (__ dirname, '../node_modules/google-proto-files'); и includeDirs: [GOOGLE_PROTOS, IMPORT_PATH] - person Olga; 16.10.2018
comment
Да, но я имел в виду именно это. Вы не можете использовать абсолютный путь в первом аргументе, то есть в основном файле прототипа для загрузки, если вы также укажете параметр includeDirs. Что касается самих элементов includeDirs, вы можете использовать относительный или абсолютный путь по своему усмотрению. Это должно быть задокументировано в разделе предупреждений loadSync () или в разделе деталей реализации, IMHO. - person Maxim Sobolev; 16.10.2018
comment
Не работает с относительными путями в insludeDirs, только с абсолютными. - person Olga; 17.10.2018
comment
Я сопровождаю этот пакет. Это ограничение не задокументировано, потому что на самом деле это ошибка в том, как обрабатывается includeDirs. Что касается относительных includeDirs путей, я бы не рекомендовал их использовать, потому что пути могут не относиться к тому, что вы ожидаете от них. - person murgatroid99; 17.10.2018

Проблема здесь в том, что путь, который возвращает protoFiles('rpc'), не работает со строкой import в вашем .proto файле. Эта строка импорта означает, что @grpc/proto-loader ищет подключаемый каталог, содержащий google/rpc/status.proto, но protoFiles('rpc') возвращает каталог, который непосредственно содержит status.proto. Итак, вам нужно изменить одну или обе эти вещи, чтобы относительные каталоги совпадали правильно.

person murgatroid99    schedule 15.10.2018
comment
Изменено на const IMPORT_PATH = path.join (__ dirname, '/../node-modules/google-proto-files'); и includeDirs: [IMPORT_PATH], но с той же ошибкой - служба не является конструктором. - person Olga; 15.10.2018
comment
Хорошо, я смог подтвердить, что здесь есть еще одна проблема. Я по-прежнему достаточно уверен, что упомянутая мною проблема является частью проблемы. - person murgatroid99; 15.10.2018
comment
Я знаю, что проблема связана с импортом, потому что я мог бы успешно создать клиента без использования status.proto (закомментировал его), но я нигде не могу найти, как правильно загружать протоколы Google. - person Olga; 15.10.2018