cloud_events 0.4.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +11 -9
- data/lib/cloud_events.rb +1 -0
- data/lib/cloud_events/content_type.rb +1 -1
- data/lib/cloud_events/errors.rb +37 -5
- data/lib/cloud_events/event.rb +1 -1
- data/lib/cloud_events/event/opaque.rb +80 -0
- data/lib/cloud_events/format.rb +202 -0
- data/lib/cloud_events/http_binding.rb +295 -155
- data/lib/cloud_events/json_format.rb +162 -51
- data/lib/cloud_events/version.rb +1 -1
- metadata +6 -4
@@ -12,72 +12,171 @@ module CloudEvents
|
|
12
12
|
# https://github.com/cloudevents/spec/blob/v1.0/json-format.md.
|
13
13
|
#
|
14
14
|
class JsonFormat
|
15
|
+
# @private
|
16
|
+
UNSPECIFIED = ::Object.new.freeze
|
17
|
+
|
15
18
|
##
|
16
|
-
# Decode an event from the given input JSON string.
|
19
|
+
# Decode an event or batch from the given input JSON string.
|
20
|
+
# See {CloudEvents::Format#decode_event} for a general description.
|
17
21
|
#
|
18
|
-
#
|
19
|
-
#
|
22
|
+
# Expects `:content` and `:content_type` arguments, and will decline the
|
23
|
+
# request unless both are provided.
|
24
|
+
#
|
25
|
+
# If decoding succeeded, returns a hash with _one of_ the following keys:
|
26
|
+
#
|
27
|
+
# * `:event` ({CloudEvents::Event}) A single event decoded from the input.
|
28
|
+
# * `:event_batch` (Array of {CloudEvents::Event}) A batch of events
|
29
|
+
# decoded from the input.
|
30
|
+
#
|
31
|
+
# @param content [String] Serialized content to decode.
|
32
|
+
# @param content_type [CloudEvents::ContentType] The input content type.
|
33
|
+
# @return [Hash] if accepting the request.
|
34
|
+
# @return [nil] if declining the request.
|
35
|
+
# @raise [CloudEvents::FormatSyntaxError] if the JSON could not be parsed
|
36
|
+
# @raise [CloudEvents::SpecVersionError] if an unsupported specversion is
|
37
|
+
# found.
|
20
38
|
#
|
21
|
-
def
|
22
|
-
|
23
|
-
|
39
|
+
def decode_event content: nil, content_type: nil, **_other_kwargs
|
40
|
+
return nil unless content && content_type&.media_type == "application" && content_type&.subtype_format == "json"
|
41
|
+
case content_type.subtype_base
|
42
|
+
when "cloudevents"
|
43
|
+
event = decode_hash_structure ::JSON.parse(content), charset_of(content)
|
44
|
+
{ event: event }
|
45
|
+
when "cloudevents-batch"
|
46
|
+
charset = charset_of content
|
47
|
+
batch = Array(::JSON.parse(content)).map do |structure|
|
48
|
+
decode_hash_structure structure, charset
|
49
|
+
end
|
50
|
+
{ event_batch: batch }
|
51
|
+
end
|
52
|
+
rescue ::JSON::JSONError
|
53
|
+
raise FormatSyntaxError, "JSON syntax error"
|
24
54
|
end
|
25
55
|
|
26
56
|
##
|
27
|
-
# Encode an event to a JSON string.
|
57
|
+
# Encode an event or batch to a JSON string. This formatter should be able
|
58
|
+
# to handle any event.
|
59
|
+
# See {CloudEvents::Format#decode_event} for a general description.
|
28
60
|
#
|
29
|
-
#
|
61
|
+
# Expects _either_ the `:event` _or_ the `:event_batch` argument, but not
|
62
|
+
# both, and will decline the request unless exactly one is provided.
|
63
|
+
#
|
64
|
+
# If encoding succeeded, returns a hash with the following keys:
|
65
|
+
#
|
66
|
+
# * `:content` (String) The serialized form of the event or batch.
|
67
|
+
# * `:content_type` ({CloudEvents::ContentType}) The content type for the
|
68
|
+
# output.
|
69
|
+
#
|
70
|
+
# @param event [CloudEvents::Event] An event to encode.
|
71
|
+
# @param event_batch [Array<CloudEvents::Event>] An event batch to encode.
|
30
72
|
# @param sort [boolean] Whether to sort keys of the JSON output.
|
31
|
-
# @return [
|
73
|
+
# @return [Hash] if accepting the request.
|
74
|
+
# @return [nil] if declining the request.
|
32
75
|
#
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
76
|
+
def encode_event event: nil, event_batch: nil, sort: false, **_other_kwargs
|
77
|
+
if event && !event_batch
|
78
|
+
structure = encode_hash_structure event
|
79
|
+
structure = sort_keys structure if sort
|
80
|
+
subtype = "cloudevents"
|
81
|
+
elsif event_batch && !event
|
82
|
+
structure = event_batch.map do |elem|
|
83
|
+
structure_elem = encode_hash_structure elem
|
84
|
+
sort ? sort_keys(structure_elem) : structure_elem
|
85
|
+
end
|
86
|
+
subtype = "cloudevents-batch"
|
87
|
+
else
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
content = ::JSON.dump structure
|
91
|
+
content_type = ContentType.new "application/#{subtype}+json; charset=#{charset_of content}"
|
92
|
+
{ content: content, content_type: content_type }
|
37
93
|
end
|
38
94
|
|
39
95
|
##
|
40
|
-
# Decode
|
96
|
+
# Decode an event data object from a JSON formatted string.
|
97
|
+
# See {CloudEvents::Format#decode_data} for a general description.
|
98
|
+
#
|
99
|
+
# Expects `:spec_version`, `:content` and `:content_type` arguments, and
|
100
|
+
# will decline the request unless all three are provided.
|
101
|
+
#
|
102
|
+
# If decoding succeeded, returns a hash with the following keys:
|
103
|
+
#
|
104
|
+
# * `:data` (Object) The payload object to set as the `data` attribute.
|
105
|
+
# * `:content_type` ({CloudEvents::ContentType}) The content type to be set
|
106
|
+
# as the `datacontenttype` attribute.
|
41
107
|
#
|
42
|
-
# @param
|
43
|
-
# @
|
108
|
+
# @param content [String] Serialized content to decode.
|
109
|
+
# @param content_type [CloudEvents::ContentType] The input content type.
|
110
|
+
# @return [Hash] if accepting the request.
|
111
|
+
# @return [nil] if declining the request.
|
112
|
+
# @raise [CloudEvents::FormatSyntaxError] if the JSON could not be parsed.
|
113
|
+
# @raise [CloudEvents::SpecVersionError] if an unsupported specversion is
|
114
|
+
# found.
|
44
115
|
#
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
116
|
+
def decode_data spec_version: nil, content: nil, content_type: nil, **_other_kwargs
|
117
|
+
return nil unless spec_version
|
118
|
+
return nil unless content
|
119
|
+
return nil unless content_type&.subtype_base == "json" || content_type&.subtype_format == "json"
|
120
|
+
unless spec_version =~ /^0\.3|1(\.|$)/
|
121
|
+
raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
|
49
122
|
end
|
123
|
+
data = ::JSON.parse content
|
124
|
+
{ data: data, content_type: content_type }
|
125
|
+
rescue ::JSON::JSONError
|
126
|
+
raise FormatSyntaxError, "JSON syntax error"
|
50
127
|
end
|
51
128
|
|
52
129
|
##
|
53
|
-
# Encode
|
130
|
+
# Encode an event data object to a JSON formatted string.
|
131
|
+
# See {CloudEvents::Format#encode_data} for a general description.
|
132
|
+
#
|
133
|
+
# Expects `:spec_version`, `:data` and `:content_type` arguments, and will
|
134
|
+
# decline the request unless all three are provided.
|
135
|
+
# The `:data` object can be any Ruby object that can be interpreted as
|
136
|
+
# JSON. Most Ruby objects will work, but normally it will be a JSON value
|
137
|
+
# type comprising hashes, arrays, strings, numbers, booleans, or nil.
|
138
|
+
#
|
139
|
+
# If decoding succeeded, returns a hash with the following keys:
|
54
140
|
#
|
55
|
-
#
|
141
|
+
# * `:content` (String) The serialized form of the data.
|
142
|
+
# * `:content_type` ({CloudEvents::ContentType}) The content type for the
|
143
|
+
# output.
|
144
|
+
#
|
145
|
+
# @param data [Object] A data object to encode.
|
146
|
+
# @param content_type [CloudEvents::ContentType] The input content type
|
56
147
|
# @param sort [boolean] Whether to sort keys of the JSON output.
|
57
|
-
# @return [
|
148
|
+
# @return [Hash] if accepting the request.
|
149
|
+
# @return [nil] if declining the request.
|
58
150
|
#
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
151
|
+
def encode_data spec_version: nil, data: UNSPECIFIED, content_type: nil, sort: false, **_other_kwargs
|
152
|
+
return nil unless spec_version
|
153
|
+
return nil if data == UNSPECIFIED
|
154
|
+
return nil unless content_type&.subtype_base == "json" || content_type&.subtype_format == "json"
|
155
|
+
unless spec_version =~ /^0\.3|1(\.|$)/
|
156
|
+
raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
|
63
157
|
end
|
64
|
-
|
158
|
+
data = sort_keys data if sort
|
159
|
+
content = ::JSON.dump data
|
160
|
+
{ content: content, content_type: content_type }
|
65
161
|
end
|
66
162
|
|
67
163
|
##
|
68
164
|
# Decode a single event from a hash data structure with keys and types
|
69
165
|
# conforming to the JSON envelope.
|
70
166
|
#
|
167
|
+
# @private
|
168
|
+
#
|
71
169
|
# @param structure [Hash] An input hash.
|
170
|
+
# @param charset [String] The charset.
|
72
171
|
# @return [CloudEvents::Event]
|
73
172
|
#
|
74
|
-
def decode_hash_structure structure
|
173
|
+
def decode_hash_structure structure, charset = nil
|
75
174
|
spec_version = structure["specversion"].to_s
|
76
175
|
case spec_version
|
77
176
|
when "0.3"
|
78
|
-
decode_hash_structure_v0 structure
|
177
|
+
decode_hash_structure_v0 structure, charset
|
79
178
|
when /^1(\.|$)/
|
80
|
-
decode_hash_structure_v1 structure
|
179
|
+
decode_hash_structure_v1 structure, charset
|
81
180
|
else
|
82
181
|
raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
|
83
182
|
end
|
@@ -87,6 +186,8 @@ module CloudEvents
|
|
87
186
|
# Encode a single event to a hash data structure with keys and types
|
88
187
|
# conforming to the JSON envelope.
|
89
188
|
#
|
189
|
+
# @private
|
190
|
+
#
|
90
191
|
# @param event [CloudEvents::Event] An input event.
|
91
192
|
# @return [String] The hash structure.
|
92
193
|
#
|
@@ -103,44 +204,51 @@ module CloudEvents
|
|
103
204
|
|
104
205
|
private
|
105
206
|
|
106
|
-
def sort_keys
|
207
|
+
def sort_keys obj
|
208
|
+
return obj unless obj.is_a? ::Hash
|
107
209
|
result = {}
|
108
|
-
|
109
|
-
result[key] =
|
210
|
+
obj.keys.sort.each do |key|
|
211
|
+
result[key] = sort_keys obj[key]
|
110
212
|
end
|
111
213
|
result
|
112
214
|
end
|
113
215
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
216
|
+
def charset_of str
|
217
|
+
encoding = str.encoding
|
218
|
+
if encoding == ::Encoding::ASCII_8BIT
|
219
|
+
"binary"
|
220
|
+
else
|
221
|
+
encoding.name.downcase
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def decode_hash_structure_v0 structure, charset
|
226
|
+
unless structure.key? "datacontenttype"
|
227
|
+
structure = structure.dup
|
228
|
+
content_type = "application/json"
|
229
|
+
content_type = "#{content_type}; charset=#{charset}" if charset
|
230
|
+
structure["datacontenttype"] = content_type
|
124
231
|
end
|
125
232
|
Event::V0.new attributes: structure
|
126
233
|
end
|
127
234
|
|
128
|
-
def decode_hash_structure_v1 structure
|
235
|
+
def decode_hash_structure_v1 structure, charset
|
129
236
|
if structure.key? "data_base64"
|
130
237
|
structure = structure.dup
|
131
238
|
structure["data"] = ::Base64.decode64 structure.delete "data_base64"
|
239
|
+
structure["datacontenttype"] ||= "application/octet-stream"
|
240
|
+
elsif !structure.key? "datacontenttype"
|
241
|
+
structure = structure.dup
|
242
|
+
content_type = "application/json"
|
243
|
+
content_type = "#{content_type}; charset=#{charset}" if charset
|
244
|
+
structure["datacontenttype"] = content_type
|
132
245
|
end
|
133
246
|
Event::V1.new attributes: structure
|
134
247
|
end
|
135
248
|
|
136
249
|
def encode_hash_structure_v0 event
|
137
250
|
structure = event.to_h
|
138
|
-
|
139
|
-
content_type = event.data_content_type
|
140
|
-
if data.is_a?(::String) && !content_type.nil? &&
|
141
|
-
(content_type.subtype == "json" || content_type.subtype_format == "json")
|
142
|
-
structure["data"] = ::JSON.parse data rescue data
|
143
|
-
end
|
251
|
+
structure["datacontenttype"] ||= "application/json"
|
144
252
|
structure
|
145
253
|
end
|
146
254
|
|
@@ -150,6 +258,9 @@ module CloudEvents
|
|
150
258
|
if data.is_a?(::String) && data.encoding == ::Encoding::ASCII_8BIT
|
151
259
|
structure.delete "data"
|
152
260
|
structure["data_base64"] = ::Base64.encode64 data
|
261
|
+
structure["datacontenttype"] ||= "application/octet-stream"
|
262
|
+
else
|
263
|
+
structure["datacontenttype"] ||= "application/json"
|
153
264
|
end
|
154
265
|
structure
|
155
266
|
end
|
data/lib/cloud_events/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloud_events
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: The official Ruby implementation of the CloudEvents Specification. Provides
|
14
14
|
data types for events, and HTTP/JSON bindings for marshalling and unmarshalling
|
@@ -28,9 +28,11 @@ files:
|
|
28
28
|
- lib/cloud_events/errors.rb
|
29
29
|
- lib/cloud_events/event.rb
|
30
30
|
- lib/cloud_events/event/field_interpreter.rb
|
31
|
+
- lib/cloud_events/event/opaque.rb
|
31
32
|
- lib/cloud_events/event/utils.rb
|
32
33
|
- lib/cloud_events/event/v0.rb
|
33
34
|
- lib/cloud_events/event/v1.rb
|
35
|
+
- lib/cloud_events/format.rb
|
34
36
|
- lib/cloud_events/http_binding.rb
|
35
37
|
- lib/cloud_events/json_format.rb
|
36
38
|
- lib/cloud_events/version.rb
|
@@ -38,10 +40,10 @@ homepage: https://github.com/cloudevents/sdk-ruby
|
|
38
40
|
licenses:
|
39
41
|
- Apache-2.0
|
40
42
|
metadata:
|
41
|
-
changelog_uri: https://cloudevents.github.io/sdk-ruby/v0.
|
43
|
+
changelog_uri: https://cloudevents.github.io/sdk-ruby/v0.5.1/file.CHANGELOG.html
|
42
44
|
source_code_uri: https://github.com/cloudevents/sdk-ruby
|
43
45
|
bug_tracker_uri: https://github.com/cloudevents/sdk-ruby/issues
|
44
|
-
documentation_uri: https://cloudevents.github.io/sdk-ruby/v0.
|
46
|
+
documentation_uri: https://cloudevents.github.io/sdk-ruby/v0.5.1
|
45
47
|
post_install_message:
|
46
48
|
rdoc_options: []
|
47
49
|
require_paths:
|