@@ -5,12 +5,15 @@ import (
55 "net/http"
66)
77
8- const mimeWildcard = "*"
8+ // MIMEWildCard is the fallback MIME type used for requests which do not match
9+ // a registered MIME type.
10+ const MIMEWildcard = "*"
911
1012var (
11- defaultMarshaler = & JSONPb {OrigName : true }
12-
13+ acceptHeader = http .CanonicalHeaderKey ("Accept" )
1314 contentTypeHeader = http .CanonicalHeaderKey ("Content-Type" )
15+
16+ defaultMarshaler = & JSONPb {OrigName : true }
1417)
1518
1619// MarshalerForRequest returns the inbound/outbound marshalers for this request.
@@ -20,117 +23,68 @@ var (
2023// exactly match in the registry.
2124// Otherwise, it follows the above logic for "*"/InboundMarshaler/OutboundMarshaler.
2225func MarshalerForRequest (mux * ServeMux , r * http.Request ) (inbound Marshaler , outbound Marshaler ) {
23- headerVals := append (append ([]string (nil ), r .Header [contentTypeHeader ]... ), "*" )
24-
25- for _ , val := range headerVals {
26- m := mux .marshalers .lookup (val )
27- if m != nil {
28- if inbound == nil {
29- inbound = m .inbound
30- }
31- if outbound == nil {
32- outbound = m .outbound
33- }
26+ for _ , acceptVal := range r .Header [acceptHeader ] {
27+ if m , ok := mux .marshalers .mimeMap [acceptVal ]; ok {
28+ outbound = m
29+ break
3430 }
35- if inbound != nil && outbound != nil {
36- // Got them both, return
37- return inbound , outbound
31+ }
32+
33+ for _ , contentTypeVal := range r .Header [contentTypeHeader ] {
34+ if m , ok := mux .marshalers .mimeMap [contentTypeVal ]; ok {
35+ inbound = m
36+ break
3837 }
3938 }
39+
4040 if inbound == nil {
41- inbound = defaultMarshaler
41+ inbound = mux . marshalers . mimeMap [ MIMEWildcard ]
4242 }
4343 if outbound == nil {
44- outbound = defaultMarshaler
44+ outbound = inbound
4545 }
46- return inbound , outbound
4746
47+ return inbound , outbound
4848}
4949
50- // marshalerRegistry keeps a mapping from MIME types to mimeMarshalers.
51- type marshalerRegistry map [string ]* mimeMarshaler
52-
53- type mimeMarshaler struct {
54- inbound Marshaler
55- outbound Marshaler
50+ // marshalerRegistry is a mapping from MIME types to Marshalers.
51+ type marshalerRegistry struct {
52+ mimeMap map [string ]Marshaler
5653}
5754
58- // addMarshaler adds an inbound and outbund marshaler for a case-sensitive MIME type string ("*" to match any MIME type).
59- // Inbound is the marshaler that is used when marshaling inbound requests from the client.
60- // Outbound is the marshaler that is used when marshaling outbound responses to the client.
61- func (r * marshalerRegistry ) add (mime string , inbound , outbound Marshaler ) error {
62- if mime == "" {
55+ // add adds a marshaler for a case-sensitive MIME type string ("*" to match any
56+ // MIME type).
57+ func (m marshalerRegistry ) add (mime string , marshaler Marshaler ) error {
58+ if len (mime ) == 0 {
6359 return errors .New ("empty MIME type" )
6460 }
65- (* r )[mime ] = & mimeMarshaler {
66- inbound : inbound ,
67- outbound : outbound ,
68- }
69- return nil
70- }
7161
72- // addInboundMarshaler adds an inbound marshaler for a case-sensitive MIME type string ("*" to match any MIME type).
73- // Inbound is the marshaler that is used when marshaling inbound requests from the client.
74- func (r * marshalerRegistry ) addInbound (mime string , inbound Marshaler ) error {
75- if mime == "" {
76- return errors .New ("empty MIME type" )
77- }
78- if entry := (* r )[mime ]; entry != nil {
79- entry .inbound = inbound
80- return nil
81- }
82- (* r )[mime ] = & mimeMarshaler {inbound : inbound }
83- return nil
84- }
62+ m .mimeMap [mime ] = marshaler
8563
86- // addOutBound adds an outbund marshaler for a case-sensitive MIME type string ("*" to match any MIME type).
87- // Outbound is the marshaler that is used when marshaling outbound responses to the client.
88- func (r * marshalerRegistry ) addOutbound (mime string , outbound Marshaler ) error {
89- mime = http .CanonicalHeaderKey (mime )
90- if mime == "" {
91- return errors .New ("empty MIME type" )
92- }
93- if entry := (* r )[mime ]; entry != nil {
94- entry .outbound = outbound
95- return nil
96- }
97- (* r )[mime ] = & mimeMarshaler {outbound : outbound }
9864 return nil
99-
10065}
10166
102- func (r * marshalerRegistry ) lookup (mime string ) * mimeMarshaler {
103- if r == nil {
104- return nil
67+ // makeMarshalerMIMERegistry returns a new registry of marshalers.
68+ // It allows for a mapping of case-sensitive Content-Type MIME type string to runtime.Marshaler interfaces.
69+ //
70+ // For example, you could allow the client to specify the use of the runtime.JSONPb marshaler
71+ // with a "applicaton/jsonpb" Content-Type and the use of the runtime.JSONBuiltin marshaler
72+ // with a "application/json" Content-Type.
73+ // "*" can be used to match any Content-Type.
74+ // This can be attached to a ServerMux with the marshaler option.
75+ func makeMarshalerMIMERegistry () marshalerRegistry {
76+ return marshalerRegistry {
77+ mimeMap : map [string ]Marshaler {
78+ MIMEWildcard : defaultMarshaler ,
79+ },
10580 }
106- return (* r )[mime ]
10781}
10882
10983// WithMarshalerOption returns a ServeMuxOption which associates inbound and outbound
11084// Marshalers to a MIME type in mux.
111- func WithMarshalerOption (mime string , in , out Marshaler ) ServeMuxOption {
112- return func (mux * ServeMux ) {
113- if err := mux .marshalers .add (mime , in , out ); err != nil {
114- panic (err )
115- }
116- }
117- }
118-
119- // WithInboundMarshalerOption returns a ServeMuxOption which associates an inbound
120- // Marshaler to a MIME type in mux.
121- func WithInboundMarshalerOption (mime string , in Marshaler ) ServeMuxOption {
122- return func (mux * ServeMux ) {
123- if err := mux .marshalers .addInbound (mime , in ); err != nil {
124- panic (err )
125- }
126- }
127- }
128-
129- // WithOutboundMarshalerOption returns a ServeMuxOption which associates an outbound
130- // Marshaler to a MIME type in mux.
131- func WithOutboundMarshalerOption (mime string , out Marshaler ) ServeMuxOption {
85+ func WithMarshalerOption (mime string , marshaler Marshaler ) ServeMuxOption {
13286 return func (mux * ServeMux ) {
133- if err := mux .marshalers .addOutbound (mime , out ); err != nil {
87+ if err := mux .marshalers .add (mime , marshaler ); err != nil {
13488 panic (err )
13589 }
13690 }
0 commit comments