我可以从服务器向客户端GRPC发送自定义错误消息吗?

Kan*_*iya 13 javascript protocol-buffers node.js 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();
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

和我的原型文件

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;
}
Run Code Online (Sandbox Code Playgroud)

当我运行cient时,每个人的结果都是这样的

服务器.

[ 'stack', 'message', 'newStatus', 'newMessage' ]
{ [Error: MY_ERROR] newStatus: 401, newMessage: 'custom unAutorized error' }
Run Code Online (Sandbox Code Playgroud)

客户.

[ 'stack', 'message', 'code', 'metadata' ]
{ [Error: MY_ERROR] code: 2, metadata: Metadata { _internal_repr: {} } }
Run Code Online (Sandbox Code Playgroud)

所以我创建的自定义javascript错误的newStatus, newMessage属性已被删除,它已转换为GRPC标准错误消息.

我的问题是

  1. 是否可以向客户端发送自定义消息?
  2. 我可以创建GRPC错误,而不是javascript错误吗?
  3. 一种向客户端发送自定义属性的方法是我认为是添加自定义数据Metadata.但我也不知道该怎么做.

msm*_*ens 9

在 gRPC Google Group 上有对同一问题的有用回复:https ://groups.google.com/d/msg/grpc-io/X_bUx3T8S7s/x38FU429CgAJ

您可以使用 Error 对象的 message 属性向客户端发送自定义状态消息。在您的示例中,即“MY_ERROR”。状态代码应该在“code”属性中,就像您在客户端看到的一样。

如果您想使用 gRPC 状态结构而不是 JavaScript 错误,您可以通过填充对象的“code”属性和“message”或“details”属性来实现。

如果你想发送元数据,你应该构造一个 grpc.Metadata 类的实例,然后将键/值对添加到结果对象中。然后,您可以将其作为回调的第三个参数传递或设置错误的“元数据”属性以将其发送给包含错误的客户端。

请注意,gRPC 使用的状态代码不是 HTTP 状态代码,而是 grpc.status 中定义的 gRPC 特定代码。您应该只使用这些代码设置错误的代码属性。如果您想发送自己的代码,请改用元数据。

我将通过一些例子来说明上面写的内容。

要发送带有错误的自定义消息,请使用消息构造一个Error。这将设置message属性:

var jsErr = new Error('Unauthorized');
Run Code Online (Sandbox Code Playgroud)

如上所述,在您的情况下直接设置 gRPC 状态代码可能没有用。但是,作为参考,可以通过错误的code属性设置 gRPC 状态代码:

jsErr.code = grpc.status.PERMISSION_DENIED;
Run Code Online (Sandbox Code Playgroud)

要发送您自己的错误代码或其他信息,请使用元数据:

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

jsErr.metadata = metadata;
Run Code Online (Sandbox Code Playgroud)

现在,如果服务器构造上述错误并且客户端输出返回的错误:

console.log(Object.getOwnPropertyNames(err));
console.log(err);
console.log(err.metadata);
Run Code Online (Sandbox Code Playgroud)

那么客户端输出是:

[ 'stack', 'message', 'code', 'metadata' ]
{ [Error: Unauthorized]
  code: 7,
  metadata: Metadata { _internal_repr: { key1: [Object], key2: [Object] } } }
Metadata { _internal_repr: { key1: [ 'value2' ], key2: [ 'value2' ] } }
Run Code Online (Sandbox Code Playgroud)


Wal*_*ril 1

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在 Client.js 内部

client.sayHello({name: user}, function(err, response) {
    var myCustomError= response.error;
    if (myCustomError) {
        console.log(Object.getOwnPropertyNames(myCustomError));
        console.log(myCustomError);
    }
});
Run Code Online (Sandbox Code Playgroud)