8 // MIMEWildcard is the fallback MIME type used for requests which do not match
9 // a registered MIME type.
10 const MIMEWildcard = "*"
13 acceptHeader = http.CanonicalHeaderKey("Accept")
14 contentTypeHeader = http.CanonicalHeaderKey("Content-Type")
16 defaultMarshaler = &JSONPb{OrigName: true}
19 // MarshalerForRequest returns the inbound/outbound marshalers for this request.
20 // It checks the registry on the ServeMux for the MIME type set by the Content-Type header.
21 // If it isn't set (or the request Content-Type is empty), checks for "*".
22 // If there are multiple Content-Type headers set, choose the first one that it can
23 // exactly match in the registry.
24 // Otherwise, it follows the above logic for "*"/InboundMarshaler/OutboundMarshaler.
25 func MarshalerForRequest(mux *ServeMux, r *http.Request) (inbound Marshaler, outbound Marshaler) {
26 for _, acceptVal := range r.Header[acceptHeader] {
27 if m, ok := mux.marshalers.mimeMap[acceptVal]; ok {
33 for _, contentTypeVal := range r.Header[contentTypeHeader] {
34 if m, ok := mux.marshalers.mimeMap[contentTypeVal]; ok {
41 inbound = mux.marshalers.mimeMap[MIMEWildcard]
47 return inbound, outbound
50 // marshalerRegistry is a mapping from MIME types to Marshalers.
51 type marshalerRegistry struct {
52 mimeMap map[string]Marshaler
55 // add adds a marshaler for a case-sensitive MIME type string ("*" to match any
57 func (m marshalerRegistry) add(mime string, marshaler Marshaler) error {
59 return errors.New("empty MIME type")
62 m.mimeMap[mime] = marshaler
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.
70 // For example, you could allow the client to specify the use of the runtime.JSONPb marshaler
71 // with a "application/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,
83 // WithMarshalerOption returns a ServeMuxOption which associates inbound and outbound
84 // Marshalers to a MIME type in mux.
85 func WithMarshalerOption(mime string, marshaler Marshaler) ServeMuxOption {
86 return func(mux *ServeMux) {
87 if err := mux.marshalers.add(mime, marshaler); err != nil {