0.3.0
Darwin moh-abks-mbp.lan 19.5.0 Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64 x86_64
tonic
I'm generating https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto using prost
then creating the below
let response = PreconditionFailure {
violations: vec! [
Violation {
r#type: e.to_string(),
subject: s.to_string(),
description: m.to_string()
}
]
};
let mut response_buffer = BytesMut::with_capacity(4096);
response.encode(&mut response_buffer).expect("encode error");
returning it as part of a tonic error;
Err(Status::with_details(
Code::FailedPrecondition,
"Failed Precondition",
Bytes::from(response_buffer),
))
i can log the error and see this;
error: Status { code: PreconditionFailure, message: "Invalid Argument", details: b"ClwKF2ludmFsaWRfcmVjaXBpZW50X3Bob25lEkFSZWNpcGllbnQgcGhvbmUgbnVtYmVyIGlzIG5vdCB2YWxpZCBmb3IgdGhlIGdpdmVuIG1vYmlsZSBvcGVyYXRvcg" }
on the other end (Golang) when I attempt to get details I get EOF error.
This is my go code to access details
func expandErrorDetails(details[] interface {})[] string {
for _, detail: = range details {
switch t: = detail.(type) {
case *epb.BadRequest:
for _, violation: = range t.GetFieldViolations() {
return [] string {
violation.GetField(),
violation.GetDescription(),
}
}
case *epb.PreconditionFailure:
for _, violation: = range t.GetViolations() {
return [] string {
violation.GetType(),
violation.GetSubject(),
violation.GetSubject(),
}
}
default:
return nil
}
}
return nil
}
by using the code here - https://github.com/hyperium/tonic/blob/372da52e96114ca76cc221f3c598be82bfae970c/tests/integration_tests/tests/status.rs#L16-L20
i'm getting transport: malformed grpc-status-details-bin: proto: invalid field number on the Go side
Yeah, this is interesting, will see if I can re-produce this tomorrow. Thanks for the report!
@moh-abk how were you able to get that specific log?
@moh-abk how were you able to get that specific log?
Do you mean this error: Status { code: PreconditionFailure, message: "Invalid Argument", details: b"ClwKF2ludmFsaWRfcmVjaXBpZW50X3Bob25lEkFSZWNpcGllbnQgcGhvbmUgbnVtYmVyIGlzIG5vdCB2YWxpZCBmb3IgdGhlIGdpdmVuIG1vYmlsZSBvcGVyYXRvcg" }?
I mean this one transport: malformed grpc-status-details-bin: proto: invalid field number
I mean this one
transport: malformed grpc-status-details-bin: proto: invalid field number
That came from Go on the other service attempting to access with_details
I doesn't work because in some implementations, Status is itself a protobuf. Errors are encoded as a repeated field of Any protos and the entire thing is sent to the client.
Something like this works with a go client. I used BadRequest but it should be the same for other errors.
async fn error_with_details(&self, _: Request<Empty>) -> Result<Response<Empty>, Status> {
let error = crate::google_rpc::BadRequest {
field_violations: vec![FieldViolation {
field: "username".to_string(),
description: "username is too short".to_string(),
}],
};
let mut buffer = BytesMut::with_capacity(4096);
error.encode(&mut buffer).expect("encoded bad request");
let status_proto = crate::google_rpc::Status {
code: Code::InvalidArgument as i32,
message: "argument is invalid".to_string(),
details: vec![prost_types::Any {
type_url: "google.rpc.BadRequest".to_string(),
value: buffer.to_vec(),
}],
};
buffer.clear();
status_proto.encode(&mut buffer).expect("encoded status");
let status = Status::with_details(
Code::InvalidArgument,
"argument is invalid",
buffer.freeze(),
);
Err(status)
}
This is the Status proto definition, which grpc-go uses internally:
https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto
I also created https://docs.rs/tonic-types/0.1.0/tonic_types/ which has the Status proto.
@alce where is crate::google_rpc::BadRequest and crate::google_rpc::Status coming from?
@moh-abk Those are just the compiled protos from https://github.com/googleapis/googleapis/tree/master/google/rpc
Closing this as it seems resolved