1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
package runtime_test
import (
"errors"
"fmt"
"io"
"net/http"
"testing"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
)
func TestMarshalerForRequest(t *testing.T) {
r, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatalf(`http.NewRequest("GET", "http://example.com", nil) failed with %v; want success`, err)
}
mux := runtime.NewServeMux()
r.Header.Set("Accept", "application/x-out")
r.Header.Set("Content-Type", "application/x-in")
in, out := runtime.MarshalerForRequest(mux, r)
if _, ok := in.(*runtime.HTTPBodyMarshaler); !ok {
t.Errorf("in = %#v; want a runtime.HTTPBodyMarshaler", in)
}
if _, ok := out.(*runtime.HTTPBodyMarshaler); !ok {
t.Errorf("out = %#v; want a runtime.HTTPBodyMarshaler", in)
}
marshalers := []dummyMarshaler{0, 1, 2}
specs := []struct {
opt runtime.ServeMuxOption
wantIn runtime.Marshaler
wantOut runtime.Marshaler
}{
// The option with wildcard overwrites the default configuration
{
opt: runtime.WithMarshalerOption(runtime.MIMEWildcard, &marshalers[0]),
wantIn: &marshalers[0],
wantOut: &marshalers[0],
},
// You can specify a marshaler for a specific MIME type.
// The output marshaler follows the input one unless specified.
{
opt: runtime.WithMarshalerOption("application/x-in", &marshalers[1]),
wantIn: &marshalers[1],
wantOut: &marshalers[1],
},
// You can also separately specify an output marshaler
{
opt: runtime.WithMarshalerOption("application/x-out", &marshalers[2]),
wantIn: &marshalers[1],
wantOut: &marshalers[2],
},
}
for i, spec := range specs {
var opts []runtime.ServeMuxOption
for _, s := range specs[:i+1] {
opts = append(opts, s.opt)
}
mux = runtime.NewServeMux(opts...)
in, out = runtime.MarshalerForRequest(mux, r)
if got, want := in, spec.wantIn; got != want {
t.Errorf("in = %#v; want %#v", got, want)
}
if got, want := out, spec.wantOut; got != want {
t.Errorf("out = %#v; want %#v", got, want)
}
}
r.Header.Set("Content-Type", "application/x-in; charset=UTF-8")
in, out = runtime.MarshalerForRequest(mux, r)
if got, want := in, &marshalers[1]; got != want {
t.Errorf("in = %#v; want %#v", got, want)
}
if got, want := out, &marshalers[2]; got != want {
t.Errorf("out = %#v; want %#v", got, want)
}
r.Header.Set("Content-Type", "application/x-another")
r.Header.Set("Accept", "application/x-another")
in, out = runtime.MarshalerForRequest(mux, r)
if got, want := in, &marshalers[0]; got != want {
t.Errorf("in = %#v; want %#v", got, want)
}
if got, want := out, &marshalers[0]; got != want {
t.Errorf("out = %#v; want %#v", got, want)
}
}
type dummyMarshaler int
func (dummyMarshaler) ContentType(_ interface{}) string { return "" }
func (dummyMarshaler) Marshal(interface{}) ([]byte, error) {
return nil, errors.New("not implemented")
}
func (dummyMarshaler) Unmarshal([]byte, interface{}) error {
return errors.New("not implemented")
}
func (dummyMarshaler) NewDecoder(r io.Reader) runtime.Decoder {
return dummyDecoder{}
}
func (dummyMarshaler) NewEncoder(w io.Writer) runtime.Encoder {
return dummyEncoder{}
}
func (m dummyMarshaler) GoString() string {
return fmt.Sprintf("dummyMarshaler(%d)", m)
}
type dummyDecoder struct{}
func (dummyDecoder) Decode(interface{}) error {
return errors.New("not implemented")
}
type dummyEncoder struct{}
func (dummyEncoder) Encode(interface{}) error {
return errors.New("not implemented")
}
|