Skip to content

Commit e946cbf

Browse files
committed
Add status serialization to metadata and send with grpc status
1 parent dfcc2f2 commit e946cbf

File tree

4 files changed

+90
-3
lines changed

4 files changed

+90
-3
lines changed

examples/error_details/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,20 @@ Run the client in another terminal. It will make two calls: first, a successful
1818
node client.js
1919
```
2020

21-
## EWxpected Output
21+
## Expected Output
2222
```
2323
Greeting: Hello World
2424
2525
--- Standard gRPC Error Received ---
2626
Code: 3
2727
Status: INVALID_ARGUMENT
2828
Message: 3 INVALID_ARGUMENT: Simple Error: The name field was empty.
29+
30+
--- Rich Error Details---
31+
Violation: [
32+
{
33+
"field": "name",
34+
"description": "Name field is required"
35+
}
36+
]
2937
```

examples/error_details/client.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ var packageDefinition = protoLoader.loadSync(
3131
});
3232
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
3333

34+
// Extract Deserializers from the service definition
35+
var serviceDef = hello_proto.Greeter.service;
36+
var decodeStatus = serviceDef['_DecodeStatus'].responseDeserialize;
37+
var decodeBadRequest = serviceDef['_DecodeBadRequest'].responseDeserialize;
38+
3439
var client = new hello_proto.Greeter('localhost:50051', grpc.credentials.createInsecure());
3540

3641
function main() {
@@ -43,10 +48,27 @@ function main() {
4348

4449
client.sayHello({ name: '' }, function (err, response) {
4550
if (err) {
46-
console.log('--- Standard gRPC Error Received ---');
51+
console.log('\n--- Standard gRPC Error Received ---');
4752
console.log(`Code: ${err.code}`);
4853
console.log(`Status: ${grpc.status[err.code]}`);
4954
console.log(`Message: ${err.message}`);
55+
56+
// Rich Error Decoding
57+
const [statusBuffer] = err.metadata?.get('grpc-status-details-bin') || [];
58+
if (statusBuffer) {
59+
console.log('\n--- Rich Error Details---');
60+
var statusObj = decodeStatus(statusBuffer);
61+
62+
if (statusObj.details) {
63+
statusObj.details.forEach(detail => {
64+
if (detail.type_url === 'type.googleapis.com/google.rpc.BadRequest') {
65+
var badRequestObj = decodeBadRequest(detail.value);
66+
console.log('Violation:', JSON.stringify(badRequestObj.field_violations, null, 2));
67+
}
68+
});
69+
}
70+
}
71+
5072
} else {
5173
console.log('Failing call unexpectedly succeeded:', response.message);
5274
}

examples/error_details/server.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,43 @@ var packageDefinition = protoLoader.loadSync(
3131
});
3232
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
3333

34+
// Extract Serializers
35+
var serviceDef = hello_proto.Greeter.service;
36+
var encodeStatus = serviceDef['_EncodeStatus'].requestSerialize;
37+
var encodeBadRequest = serviceDef['_EncodeBadRequest'].requestSerialize;
38+
3439
/**
3540
* Implements the SayHello RPC method.
3641
*/
3742
function sayHello(call, callback) {
3843
if (call.request.name === '') {
44+
//Serialize the BadRequest detail
45+
var badRequestBuffer = encodeBadRequest({
46+
field_violations: [
47+
{ field: 'name', description: 'Name field is required' }
48+
]
49+
});
50+
51+
//Create and Serialize the Status Message
52+
var statusBuffer = encodeStatus({
53+
code: 3,
54+
message: 'Request argument invalid',
55+
details: [
56+
{
57+
type_url: 'type.googleapis.com/google.rpc.BadRequest',
58+
value: badRequestBuffer
59+
}
60+
]
61+
});
62+
63+
// Attach Metadata
64+
var metadata = new grpc.Metadata();
65+
metadata.add('grpc-status-details-bin', statusBuffer);
66+
3967
callback({
4068
code: grpc.status.INVALID_ARGUMENT,
41-
details: 'Simple Error: The name field was empty.'
69+
details: 'Simple Error: The name field was empty.',
70+
metadata: metadata
4271
});
4372
return;
4473
}

examples/protos/helloworld.proto

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ service Greeter {
2727
rpc SayHello (HelloRequest) returns (HelloReply) {}
2828

2929
rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}
30+
31+
// Internal helpers to generate serializers for the server and deserializers for the client
32+
rpc _EncodeStatus (Status) returns (Empty) {}
33+
rpc _EncodeBadRequest (BadRequest) returns (Empty) {}
34+
rpc _DecodeStatus (Empty) returns (Status) {}
35+
rpc _DecodeBadRequest (Empty) returns (BadRequest) {}
3036
}
3137

3238
// The request message containing the user's name.
@@ -38,3 +44,25 @@ message HelloRequest {
3844
message HelloReply {
3945
string message = 1;
4046
}
47+
48+
// Standard definitions for rich errors
49+
message Status {
50+
int32 code = 1;
51+
string message = 2;
52+
repeated Any details = 3;
53+
}
54+
55+
message Any {
56+
string type_url = 1;
57+
bytes value = 2;
58+
}
59+
60+
message BadRequest {
61+
message FieldViolation {
62+
string field = 1;
63+
string description = 2;
64+
}
65+
repeated FieldViolation field_violations = 1;
66+
}
67+
68+
message Empty {}

0 commit comments

Comments
 (0)