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