Могу ли я отправить собственное сообщение об ошибке с сервера на клиент GRPC?

Я создал простой сервер и клиент GRPC.

Я хочу создать настраиваемую ошибку на сервере и передать ее клиенту. Мой код выглядит следующим образом:

Server.js

var error = require('error');

var PROTO_PATH = grpc.load(__dirname + '/proto/hello.proto');
var hello_proto = PROTO_PATH.hello;

function sayHello(call, callback) {

    try {
        var jsErr = new Error('MY_ERROR');
        jsErr.newStatus = 401;
        jsErr.newMessage = 'custom unAuthorized error';
        console.log(Object.getOwnPropertyNames(jsErr));
        console.log(jsErr);
        callback(jsErr);

    } catch(e) {
        callback(e);
    }
}

function sayHelloAgain(call, callback) {
    callback(null, {message: 'Hello Again ' + call.request.name});
}

function main() {

    var server = new grpc.Server();
    server.addProtoService(hello_proto.Hello.service, {sayHello: sayHello,sayHelloAgain: sayHelloAgain });
    server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
    server.start();
}

main();

Client.js

var grpc = require('grpc');

var PROTO_PATH = grpc.load(__dirname + '/proto/hello.proto');
var hello_proto = PROTO_PATH.hello;

function main() {
    var client = new hello_proto.Hello('localhost:50051',grpc.credentials.createInsecure());
    var user;
    if (process.argv.length >= 3) {
        user = process.argv[2];
    } else {
        user = 'world';
    }

    client.sayHello({name: user}, function(err, response) {

        console.log(Object.getOwnPropertyNames(err));
        console.log(err);
    });
}

main();

и мой прото-файл

syntax = "proto3";

package hello;

service Hello {
    rpc sayHello(sayHelloRequest) returns (sayHelloResponse) {}
    rpc sayHelloAgain(sayHelloRequest) returns (sayHelloResponse) {}
}


message sayHelloRequest {
    string name = 1;
}

message sayHelloResponse {
    string message = 1;
}

когда я запускаю cient, результат каждого выглядит так

Сервер.

[ 'stack', 'message', 'newStatus', 'newMessage' ]
{ [Error: MY_ERROR] newStatus: 401, newMessage: 'custom unAutorized error' }

Клиент.

[ 'stack', 'message', 'code', 'metadata' ]
{ [Error: MY_ERROR] code: 2, metadata: Metadata { _internal_repr: {} } }

Таким образом, мои созданные пользовательские свойства ошибки javascript newStatus, newMessage были удалены, и оно преобразовано в стандартное сообщение об ошибке GRPC.

Мои вопросы

  1. Можно ли отправить клиенту собственное сообщение?
  2. Могу ли я создать ошибку GRPC, а не ошибку javascript?
  3. Я думаю, что один из способов отправки настраиваемых атрибутов клиенту - это добавить настраиваемые данные в Metadata. но я тоже не знаю, как это сделать.

person Kanishka Panamaldeniya    schedule 24.11.2016    source источник


Ответы (2)


На этот же вопрос в группе gRPC Google есть полезный ответ: https://groups.google.com/d/msg/grpc-io/X_bUx3T8S7s/x38FU429CgAJ

Вы можете отправить клиенту настраиваемое сообщение о состоянии, используя свойство message объекта Error. В вашем примере это «MY_ERROR». Код состояния должен быть в свойстве «code», точно так же, как вы его видите на стороне клиента.

Если вы хотите использовать структуру статуса gRPC вместо ошибки JavaScript, вы можете сделать это, заполнив свойство «code» и свойство «message» или «details» объекта.

Если вы хотите отправить метаданные, вы должны создать экземпляр класса grpc.Metadata, а затем добавить пары ключ / значение к полученному объекту. Затем вы можете передать его в качестве третьего аргумента обратного вызова или установить свойство «метаданные» ошибки, чтобы отправить его клиенту с ошибкой.

Обратите внимание, что коды состояния, которые использует gRPC, не являются кодами состояния HTTP, а являются кодами, специфичными для gRPC, которые определены в grpc.status. Вы должны только установить свойство кода ошибки, используя эти коды. Если вы хотите отправлять свои собственные коды, используйте вместо них метаданные.

Я проиллюстрирую то, что написано выше, на нескольких примерах.

Чтобы отправить собственное сообщение с ошибкой, создайте Error с сообщением. Это устанавливает свойство message:

var jsErr = new Error('Unauthorized');

Как упоминалось выше, в вашем случае, вероятно, нецелесообразно напрямую устанавливать коды состояния gRPC. Но, для справки, код состояния gRPC может быть установлен через свойство ошибки code:

jsErr.code = grpc.status.PERMISSION_DENIED;

Чтобы отправить собственные коды ошибок или другую информацию, используйте метаданные:

var metadata = new grpc.Metadata();
metadata.set('key1', 'value2');
metadata.set('key2', 'value2');

jsErr.metadata = metadata;

Теперь, если сервер создает ошибку, как указано выше, а клиент выводит возвращенную ошибку с помощью:

console.log(Object.getOwnPropertyNames(err));
console.log(err);
console.log(err.metadata);

тогда вывод клиента:

[ 'stack', 'message', 'code', 'metadata' ]
{ [Error: Unauthorized]
  code: 7,
  metadata: Metadata { _internal_repr: { key1: [Object], key2: [Object] } } }
Metadata { _internal_repr: { key1: [ 'value2' ], key2: [ 'value2' ] } }
person Max Smolens    schedule 06.12.2016
comment
Собственно этот вопрос я тоже задаю: D. я думал, будет больше способов. в любом случае большое спасибо за ваш ответ (Y) - person Kanishka Panamaldeniya; 06.12.2016

1.Да 2.Возможно

Избегайте посылки специальных объектов (например, new Error) по проводам. Отправьте простой объект со свойством ошибки и найдите его значение на другом конце. См. http://json.org/, чтобы получить обзор легко переносимых данных.

внутри Server.js попробуйте

function sayHello(call, callback) {

    try {
        var myCustomError = {};
        myCustomError.newStatus = 401;
        myCustomError.newMessage = 'custom unAuthorized error';
        console.log(Object.getOwnPropertyNames(myCustomError ));
        console.log(myCustomError);
        callback(null, {error: myCustomError, message: ""});

    } catch(e) {
        callback(e);
    }
}

внутри Client.js

client.sayHello({name: user}, function(err, response) {
    var myCustomError= response.error;
    if (myCustomError) {
        console.log(Object.getOwnPropertyNames(myCustomError));
        console.log(myCustomError);
    }
});
person Walle Cyril    schedule 05.12.2016
comment
Хм, я могу это понять. но я хочу отправить свою ошибку в первом параметре как объект ошибки, в вашем примере вы передаете ее в параметре 2 Nd, и это не объект ошибки. - person Kanishka Panamaldeniya; 06.12.2016