How to pass a proto binary directly in a gRPC call?

Viewed 1625

I already have the proto binary of a protobuf message object.

Right now to make a gRPC call I need to unmarshal it and send over the message object to the gRPC client(which will marshal the same object again), in the process wasting latency.

How can I avoid this by passing the binary to the client?

2 Answers

This is possible using a custom codec. The custom codec can be defined as a

type StubbedCodec struct{}

func (cb StubbedCodec) Marshal(v interface{}) ([]byte, error) {
    return v.([]byte), nil
}

func (cb StubbedCodec) Unmarshal(data []byte, v interface{}) error {
    ba, _ := v.([]byte)

    for index, byte := range data {
        ba[index] = byte
    }
    return nil
}

Once we have this, we can pass the codec as a dial option as

grpc.Dial(grpcServer, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithDefaultCallOptions(grpc.ForceCodec(StubbedCodec{})))

This will force grpc to use your codec, which basically does nothing(as defined above).

If you want to send raw binary data use the protobuf type of bytes e.g.

// .proto file
message MyRawData {
  bytes rawbin = 1;
}

This will translate in go to a byte-slice, perfect for storing raw-binary:

// go-code
type MyRawData struct {   
    Rawbin []byte   `protobuf:"bytes,1,opt,name=rawbin,proto3" json:"rawbin,omitempty"`
}
Related