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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -0
- data/README.md +12 -10
- data/lib/cloud_events/content_type.rb +6 -4
- data/lib/cloud_events/errors.rb +37 -5
- data/lib/cloud_events/event/field_interpreter.rb +3 -3
- data/lib/cloud_events/event/opaque.rb +80 -0
- data/lib/cloud_events/event/v0.rb +10 -5
- data/lib/cloud_events/event/v1.rb +144 -21
- data/lib/cloud_events/event.rb +1 -1
- data/lib/cloud_events/format.rb +277 -0
- data/lib/cloud_events/http_binding.rb +335 -150
- data/lib/cloud_events/json_format.rb +232 -61
- data/lib/cloud_events/text_format.rb +73 -0
- data/lib/cloud_events/version.rb +1 -1
- data/lib/cloud_events.rb +2 -0
- metadata +7 -4
@@ -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
|