我可以从服务器发送一个自定义的错误消息到客户端GRPC?

我创build了一个简单的GRPC服务器和客户端。

我想要做的是在服务器中创build一个自定义错误,并将其传递给客户端。 我的代码如下所示:

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: {} } } 

所以我创build的自定义JavaScript错误的newStatus, newMessage属性已经删除,它已经转换为GRPC标准的错误消息。

我的问题是

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

是的,可能

避免通过电线发送特殊对象(如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); } }); 

在gRPC Google群组中有一个有用的回复: https ://groups.google.com/d/msg/grpc-io/X_bUx3T8S7s/x38FU429CgAJ

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

如果要使用gRPC状态结构而不是JavaScript错误,可以通过填充对象的“code”属性和“message”或“details”属性来完成此操作。

如果要发送元数据,则应该构造grpc.Metadata类的实例,然后将键/值对添加到生成的对象。 然后,您可以将其作为callback的第三个parameter passing,或者将错误的“元数据”属性设置为将其发送给发生错误的客户端。

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

我将用一些例子来说明上面写的东西。

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

 var jsErr = new Error('Unauthorized'); 

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

 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' ] } }