Skip to content

Instantly share code, notes, and snippets.

@Gurpartap
Created May 2, 2021 08:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gurpartap/f686150dc869263d1e921d2241a23ade to your computer and use it in GitHub Desktop.
Save Gurpartap/f686150dc869263d1e921d2241a23ade to your computer and use it in GitHub Desktop.
Parse any arbitrary http body with grpc-gateway
package body_bytes
import (
"fmt"
"io"
"io/ioutil"
"reflect"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
)
// grpc or grpc-gateway does not have an easy way to read the http body into an
// annotated body field. so we create a custom marshaller overriding only the
// decoder to read the http body into a `bytes` field. based on
// - https://rogchap.com/2019/10/19/webhook-endpoint-for-grpc-gateway/
// - https://github.com/grpc-ecosystem/grpc-gateway/issues/652
//
// requires `bytes` type for the body field.
//
// usage:
// // custom marshaller for reading whole body into a variable
// runtime.WithMarshalerOption(
// body_bytes.RawBytesMIME,
// &body_bytes.RawBytesPb{JSONPb: &runtime.JSONPb{}},
// ),
//
// alternatively, use envoy's grpc json transcoder filter, with which you can
// set `google.api.HttpBody` type for the annotated body field, and skip all
// this.
var (
RawBytesMIME = "application/raw-bytes"
RawBytesType = reflect.TypeOf([]byte(nil))
)
type RawBytesPb struct {
*runtime.JSONPb
}
func (RawBytesPb) NewDecoder(r io.Reader) runtime.Decoder {
return runtime.DecoderFunc(func(v interface{}) error {
raw, err := ioutil.ReadAll(r)
if err != nil {
return err
}
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return fmt.Errorf("%T is not a pointer", v)
}
rv = rv.Elem()
if rv.Type() != RawBytesType {
return fmt.Errorf("type must be []byte but got %T", v)
}
rv.Set(reflect.ValueOf(raw))
return nil
})
}
func (*RawBytesPb) ContentType(v interface{}) string {
return RawBytesMIME
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment