简体   繁体   English

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

[英]Can I send a custom Error message from server to client GRPC?

I have created a simple GRPC server and client . 我创建了一个简单的GRPC服务器和客户端。

What i want to do is to create a custom error in the server and pass it to the client. 我想要做的是在服务器中创建自定义错误并将其传递给客户端。 My code looks as follows: 我的代码如下:

Server.js 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 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();

and my proto file 和我的原型文件

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

when i run the cient the result from each looks like this 当我运行cient时,每个人的结果都是这样的

Server . 服务器。

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

Client . 客户。

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

So my created custom javascript error's newStatus, newMessage properties have removed and it has converted to GRPC standard error message . 所以我创建的自定义javascript错误的newStatus, newMessage属性已被删除,它已转换为GRPC标准错误消息。

My Questions are 我的问题是

  1. Is it possible to send a custom message to client ? 是否可以向客户端发送自定义消息?
  2. Can i create a GRPC error , not a javascript error ? 我可以创建GRPC错误,而不是javascript错误吗?
  3. one way to send custom attributes to client is i think is add the custom data to Metadata . 向客户端发送自定义属性的一种方法是我想将自定义数据添加到Metadata but i am also not sure how to do it . 但我也不知道该怎么做。

There is a helpful reply to this same question on the gRPC Google Group: https://groups.google.com/d/msg/grpc-io/X_bUx3T8S7s/x38FU429CgAJ gRPC Google Group对此同一问题的回复非常有用: https ://groups.google.com/d/msg/grpc-io/X_bUx3T8S7s/x38FU429CgAJ

You can send a custom status message to the client using the Error object's message property. 您可以使用Error对象的message属性向客户端发送自定义状态消息。 In your example, that is "MY_ERROR". 在您的示例中,这是“MY_ERROR”。 The status code should be in the "code" property, just like how you see it on the client side. 状态代码应该在“代码”属性中,就像您在客户端看到的那样。

If you want to use the gRPC status structure instead of a JavaScript error, you can do so by populating the "code" property and the "message" or "details" property of the object. 如果要使用gRPC状态结构而不是JavaScript错误,可以通过填充对象的“code”属性和“message”或“details”属性来实现。

If you want to send metadata, you should construct an instance of the grpc.Metadata class, then add key/value pairs to the resulting object. 如果要发送元数据,则应构造grpc.Metadata类的实例,然后将键/值对添加到结果对象中。 Then you can pass it as the third argument of the callback or set the error's "metadata" property to send it to the client with the error. 然后,您可以将其作为回调的第三个参数传递,或者设置错误的“元数据”属性以将其发送到具有错误的客户端。

Please note that the status codes that gRPC uses are not HTTP status codes, but gRPC specific codes that are defined in grpc.status. 请注意,gRPC使用的状态代码不是HTTP状态代码,而是grpc.status中定义的gRPC特定代码。 You should only set the error's code property using those codes. 您应该只使用这些代码设置错误的代码属性。 If you want to send your own codes, use metadata instead. 如果要发送自己的代码,请改用元数据。

I'll illustrate what's written above with some examples. 我将用一些例子说明上面写的内容。

To send a custom message with the error, construct an Error with the message. 要发送带有错误的自定义消息,请使用消息构造Error This sets the message property: 这将设置message属性:

var jsErr = new Error('Unauthorized');

As mentioned above, it's probably not useful to directly set gRPC status codes in your case. 如上所述,在您的情况下直接设置gRPC状态代码可能没有用。 But, for reference, the gRPC status code can be set through the error's code property: 但是,作为参考,可以通过错误的code属性设置gRPC状态代码:

jsErr.code = grpc.status.PERMISSION_DENIED;

To send your own error codes, or other information, use metadata: 要发送您自己的错误代码或其他信息,请使用元数据:

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

jsErr.metadata = metadata;

Now, if the server constructs the error as above and the client outputs the returned error with: 现在,如果服务器如上构造错误,并且客户端输出返回的错误:

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

then the client output is: 然后客户端输出是:

[ 'stack', 'message', 'code', 'metadata' ]
{ [Error: Unauthorized]
  code: 7,
  metadata: Metadata { _internal_repr: { key1: [Object], key2: [Object] } } }
Metadata { _internal_repr: { key1: [ 'value2' ], key2: [ 'value2' ] } }

1.Yes 2.Maybe 是的2.可能

Avoid sending special objects (like new Error ) over the wire. 避免通过电线发送特殊对象(如new Error )。 Send simple object with an error property and look for its value on the other end. 发送带有error属性的简单对象,并在另一端查找其值。 See http://json.org/ to have an overview of easy transferable data. 请参阅http://json.org/以概述易于转移的数据。

inside Server.js try 在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);
    }
}

inside the Client.js 在Client.js中

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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