cloud_events 0.3.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,277 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "json"
5
+
6
+ module CloudEvents
7
+ ##
8
+ # This module documents the method signatures that may be implemented by
9
+ # formatters.
10
+ #
11
+ # A formatter is an object that implements "structured" event encoding and
12
+ # decoding strategies for a particular format (such as JSON). In general,
13
+ # this includes four operations:
14
+ #
15
+ # * Decoding an entire event or batch of events from a input source.
16
+ # This is implemented by the {Format#decode_event} method.
17
+ # * Encoding an entire event or batch of events to an output sink.
18
+ # This is implemented by the {Format#encode_event} method.
19
+ # * Decoding an event payload (i.e. the `data` attribute) Ruby object from a
20
+ # serialized representation.
21
+ # This is implemented by the {Format#decode_data} method.
22
+ # * Encoding an event payload (i.e. the `data` attribute) Ruby object to a
23
+ # serialized representation.
24
+ # This is implemented by the {Format#encode_data} method.
25
+ #
26
+ # Each method takes a set of keyword arguments, and returns either a `Hash`
27
+ # or `nil`. A Hash indicates that the formatter understands the request and
28
+ # is returning its response. A return value of `nil` means the formatter does
29
+ # not understand the request and is declining to perform the operation. In
30
+ # such a case, it is possible that a different formatter should handle it.
31
+ #
32
+ # Both the keyword arguments recognized and the returned hash members may
33
+ # vary from formatter to formatter; similarly, the keyword arguments provided
34
+ # and the resturned hash members recognized may also vary for different
35
+ # callers. This interface will define a set of common argument and result key
36
+ # names, but both callers and formatters must gracefully handle the case of
37
+ # missing or extra information. For example, if a formatter expects a certain
38
+ # argument but does not receive it, it can assume the caller does not have
39
+ # the required information, and it may respond by returning `nil` to decline
40
+ # the request. Similarly, if a caller expects a response key but does not
41
+ # receive it, it can assume the formatter does not provide it, and it may
42
+ # respond by trying a different formatter.
43
+ #
44
+ # Additionally, any particular formatter need not implement all methods. For
45
+ # example, an event formatter would generally implement {Format#decode_event}
46
+ # and {Format#encode_event}, but might not implement {Format#decode_data} or
47
+ # {Format#encode_data}.
48
+ #
49
+ # Finally, this module itself is present primarily for documentation, and
50
+ # need not be directly included by formatter implementations.
51
+ #
52
+ module Format
53
+ ##
54
+ # Decode an event or batch from the given serialized input. This is
55
+ # typically called by a protocol binding to deserialize event data from an
56
+ # input stream.
57
+ #
58
+ # Common arguments include:
59
+ #
60
+ # * `:content` (String) Serialized content to decode. For example, it could
61
+ # be from an HTTP request body.
62
+ # * `:content_type` ({CloudEvents::ContentType}) The content type. For
63
+ # example, it could be from the `Content-Type` header of an HTTP request.
64
+ #
65
+ # The formatter must first determine whether it is able to interpret the
66
+ # given input. Typically, this is done by inspecting the `content_type`.
67
+ # If the formatter determines that it is unable to interpret the input, it
68
+ # should return `nil`. Otherwise, if the formatter determines it can decode
69
+ # the input, it should return a `Hash`. Common hash keys include:
70
+ #
71
+ # * `:event` ({CloudEvents::Event}) A single event decoded from the input.
72
+ # * `:event_batch` (Array of {CloudEvents::Event}) A batch of events
73
+ # decoded from the input.
74
+ #
75
+ # The formatter may also raise a {CloudEvents::CloudEventsError} subclass
76
+ # if it understood the request but determines that the input source is
77
+ # malformed.
78
+ #
79
+ # @param _kwargs [keywords] Arguments
80
+ # @return [Hash] if accepting the request and returning a result
81
+ # @return [nil] if declining the request.
82
+ #
83
+ def decode_event **_kwargs
84
+ nil
85
+ end
86
+
87
+ ##
88
+ # Encode an event or batch to a string. This is typically called by a
89
+ # protocol binding to serialize event data to an output stream.
90
+ #
91
+ # Common arguments include:
92
+ #
93
+ # * `:event` ({CloudEvents::Event}) A single event to encode.
94
+ # * `:event_batch` (Array of {CloudEvents::Event}) A batch of events to
95
+ # encode.
96
+ #
97
+ # The formatter must first determine whether it is able to interpret the
98
+ # given input. Typically, most formatters should be able to handle any
99
+ # event or event batch, but a specialized formatter that can handle only
100
+ # certain kinds of events may return `nil` to decline unwanted inputs.
101
+ # Otherwise, if the formatter determines it can encode the input, it should
102
+ # return a `Hash`. common hash keys include:
103
+ #
104
+ # * `:content` (String) The serialized form of the event. This might, for
105
+ # example, be written to an HTTP request body. Care should be taken to
106
+ # set the string's encoding properly. In particular, to output binary
107
+ # data, the encoding should probably be set to `ASCII_8BIT`.
108
+ # * `:content_type` ({CloudEvents::ContentType}) The content type for the
109
+ # output. This might, for example, be written to the `Content-Type`
110
+ # header of an HTTP request.
111
+ #
112
+ # The formatter may also raise a {CloudEvents::CloudEventsError} subclass
113
+ # if it understood the request but determines that the input source is
114
+ # malformed.
115
+ #
116
+ # @param _kwargs [keywords] Arguments
117
+ # @return [Hash] if accepting the request and returning a result
118
+ # @return [nil] if declining the request.
119
+ #
120
+ def encode_event **_kwargs
121
+ nil
122
+ end
123
+
124
+ ##
125
+ # Decode an event data object from string format. This is typically called
126
+ # by a protocol binding to deserialize the payload (i.e. `data` attribute)
127
+ # of an event as part of "binary content mode" decoding.
128
+ #
129
+ # Common arguments include:
130
+ #
131
+ # * `:spec_version` (String) The `specversion` of the event.
132
+ # * `:content` (String) Serialized payload to decode. For example, it could
133
+ # be from an HTTP request body.
134
+ # * `:content_type` ({CloudEvents::ContentType}) The content type. For
135
+ # example, it could be from the `Content-Type` header of an HTTP request.
136
+ #
137
+ # The formatter must first determine whether it is able to interpret the
138
+ # given input. Typically, this is done by inspecting the `content_type`.
139
+ # If the formatter determines that it is unable to interpret the input, it
140
+ # should return `nil`. Otherwise, if the formatter determines it can decode
141
+ # the input, it should return a `Hash`. Common hash keys include:
142
+ #
143
+ # * `:data` (Object) The payload object to be set as the `data` attribute
144
+ # in a {CloudEvents::Event} object.
145
+ # * `:content_type` ({CloudEvents::ContentType}) The content type to be set
146
+ # as the `datacontenttype` attribute in a {CloudEvents::Event} object.
147
+ # In many cases, this may simply be copied from the `:content_type`
148
+ # argument, but a formatter could modify it to provide corrections or
149
+ # additional information.
150
+ #
151
+ # The formatter may also raise a {CloudEvents::CloudEventsError} subclass
152
+ # if it understood the request but determines that the input source is
153
+ # malformed.
154
+ #
155
+ # @param _kwargs [keywords] Arguments
156
+ # @return [Hash] if accepting the request and returning a result
157
+ # @return [nil] if declining the request.
158
+ #
159
+ def decode_data **_kwargs
160
+ nil
161
+ end
162
+
163
+ ##
164
+ # Encode an event data object to string format. This is typically called by
165
+ # a protocol binding to serialize the payload (i.e. `data` attribute and
166
+ # corresponding `datacontenttype` attribute) of an event as part of "binary
167
+ # content mode" encoding.
168
+ #
169
+ # Common arguments include:
170
+ #
171
+ # * `:spec_version` (String) The `specversion` of the event.
172
+ # * `:data` (Object) The payload object from an event's `data` attribute.
173
+ # * `:content_type` ({CloudEvents::ContentType}) The content type from an
174
+ # event's `datacontenttype` attribute.
175
+ #
176
+ # The formatter must first determine whether it is able to interpret the
177
+ # given input. Typically, this is done by inspecting the `content_type`.
178
+ # If the formatter determines that it is unable to interpret the input, it
179
+ # should return `nil`. Otherwise, if the formatter determines it can decode
180
+ # the input, it should return a `Hash`. Common hash keys include:
181
+ #
182
+ # * `:content` (String) The serialized form of the data. This might, for
183
+ # example, be written to an HTTP request body. Care should be taken to
184
+ # set the string's encoding properly. In particular, to output binary
185
+ # data, the encoding should generally be set to `ASCII_8BIT`.
186
+ # * `:content_type` ({CloudEvents::ContentType}) The content type for the
187
+ # output. This might, for example, be written to the `Content-Type`
188
+ # header of an HTTP request.
189
+ #
190
+ # The formatter may also raise a {CloudEvents::CloudEventsError} subclass
191
+ # if it understood the request but determines that the input source is
192
+ # malformed.
193
+ #
194
+ # @param _kwargs [keywords] Arguments
195
+ # @return [Hash] if accepting the request and returning a result
196
+ # @return [nil] if declining the request.
197
+ #
198
+ def encode_data **_kwargs
199
+ nil
200
+ end
201
+
202
+ ##
203
+ # A convenience formatter that checks multiple formats for one capable of
204
+ # handling the given input.
205
+ #
206
+ class Multi
207
+ ##
208
+ # Create a multi format.
209
+ #
210
+ # @param formats [Array<Format>] An array of formats to check in order
211
+ # @param result_checker [Proc] An optional block that determines whether
212
+ # a result provided by a format is acceptable. The block takes the
213
+ # format's result as an argument, and returns either the result to
214
+ # indicate acceptability, or `nil` to indicate not.
215
+ #
216
+ def initialize formats = [], &result_checker
217
+ @formats = formats
218
+ @result_checker = result_checker
219
+ end
220
+
221
+ ##
222
+ # The formats to check, in order.
223
+ #
224
+ # @return [Array<Format>]
225
+ #
226
+ attr_reader :formats
227
+
228
+ ##
229
+ # Implements {Format#decode_event}
230
+ #
231
+ def decode_event **kwargs
232
+ @formats.each do |elem|
233
+ result = elem.decode_event(**kwargs)
234
+ result = @result_checker.call result if @result_checker
235
+ return result if result
236
+ end
237
+ nil
238
+ end
239
+
240
+ ##
241
+ # Implements {Format#encode_event}
242
+ #
243
+ def encode_event **kwargs
244
+ @formats.each do |elem|
245
+ result = elem.encode_event(**kwargs)
246
+ result = @result_checker.call result if @result_checker
247
+ return result if result
248
+ end
249
+ nil
250
+ end
251
+
252
+ ##
253
+ # Implements {Format#decode_data}
254
+ #
255
+ def decode_data **kwargs
256
+ @formats.each do |elem|
257
+ result = elem.decode_data(**kwargs)
258
+ result = @result_checker.call result if @result_checker
259
+ return result if result
260
+ end
261
+ nil
262
+ end
263
+
264
+ ##
265
+ # Implements {Format#encode_data}
266
+ #
267
+ def encode_data **kwargs
268
+ @formats.each do |elem|
269
+ result = elem.encode_data(**kwargs)
270
+ result = @result_checker.call result if @result_checker
271
+ return result if result
272
+ end
273
+ nil
274
+ end
275
+ end
276
+ end
277
+ end