-
Notifications
You must be signed in to change notification settings - Fork 36
/
format.go
124 lines (100 loc) · 3.32 KB
/
format.go
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
package grpcall
import (
"bytes"
"encoding/json"
"fmt"
"io"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/jhump/protoreflect/dynamic"
)
type Format string
const (
FormatJSON = Format("json")
)
// RequestParser processes input into messages.
type RequestParser interface {
// Next parses input data into the given request message. If called after
// input is exhausted, it returns io.EOF. If the caller re-uses the same
// instance in multiple calls to Next, it should call msg.Reset() in between
// each call.
Next(msg proto.Message) error
}
type jsonRequestParser struct {
dec *json.Decoder
unmarshaler jsonpb.Unmarshaler
}
// NewJSONRequestParser returns a RequestParser that reads data in JSON format
// from the given reader.
func NewJSONRequestParser(in io.Reader, resolver jsonpb.AnyResolver) RequestParser {
return &jsonRequestParser{
dec: json.NewDecoder(in),
unmarshaler: jsonpb.Unmarshaler{AnyResolver: resolver},
}
}
func (f *jsonRequestParser) Next(m proto.Message) error {
var msg json.RawMessage
if err := f.dec.Decode(&msg); err != nil {
return err
}
return f.unmarshaler.Unmarshal(bytes.NewReader(msg), m)
}
// Formatter translates messages into string representations.
type Formatter func(proto.Message) (string, error)
// NewJSONFormatter returns a formatter that returns JSON strings.
func NewJSONFormatter(emitDefaults bool, resolver jsonpb.AnyResolver) Formatter {
marshaler := jsonpb.Marshaler{
EmitDefaults: emitDefaults,
Indent: " ",
AnyResolver: resolver,
}
return marshaler.MarshalToString
}
func anyResolver(source DescriptorSource) (jsonpb.AnyResolver, error) {
files, _ := GetAllFiles(source)
var er dynamic.ExtensionRegistry
for _, fd := range files {
er.AddExtensionsFromFile(fd)
}
mf := dynamic.NewMessageFactoryWithExtensionRegistry(&er)
return dynamic.AnyResolver(mf, files...), nil
}
// RequestParserAndFormatterFor returns a request parser and formatter for the given format.
func RequestParserAndFormatterFor(descSource DescriptorSource, emitJSONDefaultFields bool, in io.Reader) (RequestParser, Formatter, error) {
resolver, err := anyResolver(descSource)
if err != nil {
return nil, nil, fmt.Errorf("error creating message resolver: %v", err)
}
return NewJSONRequestParser(in, resolver), NewJSONFormatter(emitJSONDefaultFields, resolver), nil
}
func RequestParserFor(descSource DescriptorSource, in io.Reader) (RequestParser, error) {
resolver, err := anyResolver(descSource)
if err != nil {
return nil, fmt.Errorf("error creating message resolver: %v", err)
}
return NewJSONRequestParser(in, resolver), nil
}
func ParseFormatterByDesc(descSource DescriptorSource, emitFields bool) (Formatter, error) {
resolver, err := anyResolver(descSource)
return NewJSONFormatter(emitFields, resolver), err
}
type EventHandler struct {
descSource DescriptorSource
formatter func(proto.Message) (string, error)
}
var DefaultEventHandler *EventHandler
func SetDefaultEventHandler(descSource DescriptorSource, formatter Formatter) *EventHandler {
en := &EventHandler{
descSource: descSource,
formatter: formatter,
}
DefaultEventHandler = en
return en
}
func (h *EventHandler) FormatResponse(resp proto.Message) string {
if respStr, err := h.formatter(resp); err != nil {
return ""
} else {
return respStr
}
}