cloud_events 0.2.0 → 0.3.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 +5 -0
- data/README.md +3 -3
- data/lib/cloud_events/content_type.rb +2 -2
- data/lib/cloud_events/event/field_interpreter.rb +22 -44
- data/lib/cloud_events/event/utils.rb +51 -0
- data/lib/cloud_events/event/v0.rb +9 -4
- data/lib/cloud_events/event/v1.rb +9 -4
- data/lib/cloud_events/http_binding.rb +17 -9
- data/lib/cloud_events/json_format.rb +3 -4
- data/lib/cloud_events/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 561f1577a53c99db91573da43e0caa899add4388169a8c4784910dbfb3ae94d7
|
4
|
+
data.tar.gz: eb936cd23fbbd2b2658ec8a5c52ad5857c50b8f81019e15f341bdeb89346d037
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c702c7b33d247b38c9ef8c46dc0d0ef3253d5ffe5d6e8ba7ba6043a0d0f597b748c40514bbe94f0836c150d5f7336e67005f550bbabe6ecfefd73b6f9925ff0
|
7
|
+
data.tar.gz: f765051aec3c216b36eafdd082f771701d8647d7c4cead2489a61370fb598390fb5d7f43b138a7ab0af91a039d4a88e36c9f4897e91d37650220b474260c9d3d
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -17,7 +17,7 @@ Features:
|
|
17
17
|
specifications.
|
18
18
|
* Extensible to additional formats and protocol bindings, and future
|
19
19
|
specification versions.
|
20
|
-
* Compatible with Ruby 2.
|
20
|
+
* Compatible with Ruby 2.5 or later, or JRuby 9.2.x or later. No runtime gem
|
21
21
|
dependencies.
|
22
22
|
|
23
23
|
## Quickstart
|
@@ -35,7 +35,7 @@ A simple [Sinatra](https://sinatrarb.com) app that receives CloudEvents:
|
|
35
35
|
```ruby
|
36
36
|
# examples/server/Gemfile
|
37
37
|
source "https://rubygems.org"
|
38
|
-
gem "cloud_events", "~> 0.
|
38
|
+
gem "cloud_events", "~> 0.2"
|
39
39
|
gem "sinatra", "~> 2.0"
|
40
40
|
```
|
41
41
|
|
@@ -59,7 +59,7 @@ A simple Ruby script that sends a CloudEvent:
|
|
59
59
|
```ruby
|
60
60
|
# examples/client/Gemfile
|
61
61
|
source "https://rubygems.org"
|
62
|
-
gem "cloud_events", "~> 0.
|
62
|
+
gem "cloud_events", "~> 0.2"
|
63
63
|
```
|
64
64
|
|
65
65
|
```ruby
|
@@ -140,7 +140,7 @@ module CloudEvents
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def consume_token str, downcase: false, error_message: nil
|
143
|
-
match = /^([\w
|
143
|
+
match = /^([\w!#$%&'*+.\^`{|}-]+)(.*)$/.match str
|
144
144
|
raise ParseError, error_message || "Expected token" unless match
|
145
145
|
token = match[1]
|
146
146
|
token.downcase! if downcase
|
@@ -203,7 +203,7 @@ module CloudEvents
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def maybe_quote str
|
206
|
-
return str if /^[\w
|
206
|
+
return str if /^[\w!#$%&'*+.\^`{|}-]+$/ =~ str
|
207
207
|
str = str.gsub("\\", "\\\\\\\\").gsub("\"", "\\\\\"")
|
208
208
|
"\"#{str}\""
|
209
209
|
end
|
@@ -1,15 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "cloud_events/event/utils"
|
4
|
+
|
3
5
|
module CloudEvents
|
4
6
|
module Event
|
5
7
|
##
|
6
8
|
# A helper that extracts and interprets event fields from an input hash.
|
7
|
-
#
|
8
9
|
# @private
|
9
10
|
#
|
10
11
|
class FieldInterpreter
|
11
12
|
def initialize args
|
12
|
-
@args = keys_to_strings args
|
13
|
+
@args = Utils.keys_to_strings args
|
13
14
|
@attributes = {}
|
14
15
|
end
|
15
16
|
|
@@ -26,6 +27,7 @@ module CloudEvents
|
|
26
27
|
case value
|
27
28
|
when ::String
|
28
29
|
raise AttributeError, "The #{keys.first} field cannot be empty" if value.empty?
|
30
|
+
value.freeze
|
29
31
|
[value, value]
|
30
32
|
else
|
31
33
|
raise AttributeError, "Illegal type for #{keys.first}:" \
|
@@ -40,12 +42,12 @@ module CloudEvents
|
|
40
42
|
when ::String
|
41
43
|
raise AttributeError, "The #{keys.first} field cannot be empty" if value.empty?
|
42
44
|
begin
|
43
|
-
[::URI.parse(value), value]
|
45
|
+
[Utils.deep_freeze(::URI.parse(value)), value.freeze]
|
44
46
|
rescue ::URI::InvalidURIError => e
|
45
47
|
raise AttributeError, "Illegal format for #{keys.first}: #{e.message}"
|
46
48
|
end
|
47
49
|
when ::URI::Generic
|
48
|
-
[value, value.to_s]
|
50
|
+
[Utils.deep_freeze(value), value.to_s.freeze]
|
49
51
|
else
|
50
52
|
raise AttributeError, "Illegal type for #{keys.first}:" \
|
51
53
|
" String or URI expected but #{value.class} found"
|
@@ -58,15 +60,15 @@ module CloudEvents
|
|
58
60
|
case value
|
59
61
|
when ::String
|
60
62
|
begin
|
61
|
-
[::DateTime.rfc3339(value), value]
|
63
|
+
[Utils.deep_freeze(::DateTime.rfc3339(value)), value.freeze]
|
62
64
|
rescue ::Date::Error => e
|
63
65
|
raise AttributeError, "Illegal format for #{keys.first}: #{e.message}"
|
64
66
|
end
|
65
67
|
when ::DateTime
|
66
|
-
[value, value.rfc3339]
|
68
|
+
[Utils.deep_freeze(value), value.rfc3339.freeze]
|
67
69
|
when ::Time
|
68
70
|
value = value.to_datetime
|
69
|
-
[value, value.rfc3339]
|
71
|
+
[Utils.deep_freeze(value), value.rfc3339.freeze]
|
70
72
|
else
|
71
73
|
raise AttributeError, "Illegal type for #{keys.first}:" \
|
72
74
|
" String, Time, or DateTime expected but #{value.class} found"
|
@@ -79,7 +81,7 @@ module CloudEvents
|
|
79
81
|
case value
|
80
82
|
when ::String
|
81
83
|
raise AttributeError, "The #{keys.first} field cannot be empty" if value.empty?
|
82
|
-
[ContentType.new(value), value]
|
84
|
+
[ContentType.new(value), value.freeze]
|
83
85
|
when ContentType
|
84
86
|
[value, value.to_s]
|
85
87
|
else
|
@@ -94,6 +96,7 @@ module CloudEvents
|
|
94
96
|
case value
|
95
97
|
when ::String
|
96
98
|
raise SpecVersionError, "Unrecognized specversion: #{value}" unless accept =~ value
|
99
|
+
value.freeze
|
97
100
|
[value, value]
|
98
101
|
else
|
99
102
|
raise AttributeError, "Illegal type for #{keys.first}:" \
|
@@ -102,8 +105,17 @@ module CloudEvents
|
|
102
105
|
end
|
103
106
|
end
|
104
107
|
|
108
|
+
def data_object keys, required: false
|
109
|
+
object keys, required: required, allow_nil: true do |value|
|
110
|
+
Utils.deep_freeze value
|
111
|
+
[value, value]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
105
115
|
UNDEFINED = ::Object.new.freeze
|
106
116
|
|
117
|
+
private
|
118
|
+
|
107
119
|
def object keys, required: false, allow_nil: false
|
108
120
|
value = UNDEFINED
|
109
121
|
keys.each do |key|
|
@@ -115,44 +127,10 @@ module CloudEvents
|
|
115
127
|
raise AttributeError, "The #{keys.first} field is required" if required
|
116
128
|
return nil
|
117
129
|
end
|
118
|
-
|
119
|
-
|
120
|
-
deep_freeze converted
|
121
|
-
else
|
122
|
-
converted = raw = value
|
123
|
-
end
|
124
|
-
@attributes[keys.first.freeze] = raw.freeze
|
130
|
+
converted, raw = yield value
|
131
|
+
@attributes[keys.first.freeze] = raw
|
125
132
|
converted
|
126
133
|
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
def deep_freeze obj
|
131
|
-
case obj
|
132
|
-
when ::Hash
|
133
|
-
obj.each do |key, val|
|
134
|
-
deep_freeze key
|
135
|
-
deep_freeze val
|
136
|
-
end
|
137
|
-
when ::Array
|
138
|
-
obj.each do |val|
|
139
|
-
deep_freeze val
|
140
|
-
end
|
141
|
-
else
|
142
|
-
obj.instance_variables.each do |iv|
|
143
|
-
deep_freeze obj.instance_variable_get iv
|
144
|
-
end
|
145
|
-
end
|
146
|
-
obj.freeze
|
147
|
-
end
|
148
|
-
|
149
|
-
def keys_to_strings hash
|
150
|
-
result = {}
|
151
|
-
hash.each do |key, val|
|
152
|
-
result[key.to_s] = val
|
153
|
-
end
|
154
|
-
result
|
155
|
-
end
|
156
134
|
end
|
157
135
|
end
|
158
136
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CloudEvents
|
4
|
+
module Event
|
5
|
+
##
|
6
|
+
# A variety of helper methods.
|
7
|
+
# @private
|
8
|
+
#
|
9
|
+
module Utils
|
10
|
+
class << self
|
11
|
+
def deep_freeze obj
|
12
|
+
case obj
|
13
|
+
when ::Hash
|
14
|
+
obj.each do |key, val|
|
15
|
+
deep_freeze key
|
16
|
+
deep_freeze val
|
17
|
+
end
|
18
|
+
when ::Array
|
19
|
+
obj.each do |val|
|
20
|
+
deep_freeze val
|
21
|
+
end
|
22
|
+
else
|
23
|
+
obj.instance_variables.each do |iv|
|
24
|
+
deep_freeze obj.instance_variable_get iv
|
25
|
+
end
|
26
|
+
end
|
27
|
+
obj.freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
def deep_dup obj
|
31
|
+
case obj
|
32
|
+
when ::Hash
|
33
|
+
obj.each_with_object({}) { |(key, val), hash| hash[deep_dup key] = deep_dup val }
|
34
|
+
when ::Array
|
35
|
+
obj.map { |val| deep_dup val }
|
36
|
+
else
|
37
|
+
obj.dup
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def keys_to_strings hash
|
42
|
+
result = {}
|
43
|
+
hash.each do |key, val|
|
44
|
+
result[key.to_s] = val
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -3,6 +3,9 @@
|
|
3
3
|
require "date"
|
4
4
|
require "uri"
|
5
5
|
|
6
|
+
require "cloud_events/event/field_interpreter"
|
7
|
+
require "cloud_events/event/utils"
|
8
|
+
|
6
9
|
module CloudEvents
|
7
10
|
module Event
|
8
11
|
##
|
@@ -43,7 +46,7 @@ module CloudEvents
|
|
43
46
|
# field.
|
44
47
|
# * **:type** [`String`] - _required_ - The event `type` field.
|
45
48
|
# * **:data** [`Object`] - _optional_ - The data associated with the
|
46
|
-
# event (i.e. the `data` field.
|
49
|
+
# event (i.e. the `data` field).
|
47
50
|
# * **:data_content_encoding** (or **:datacontentencoding**)
|
48
51
|
# [`String`] - _optional_ - The content-encoding for the data (i.e.
|
49
52
|
# the `datacontentencoding` field.)
|
@@ -74,7 +77,7 @@ module CloudEvents
|
|
74
77
|
@id = interpreter.string ["id"], required: true
|
75
78
|
@source = interpreter.uri ["source"], required: true
|
76
79
|
@type = interpreter.string ["type"], required: true
|
77
|
-
@data = interpreter.
|
80
|
+
@data = interpreter.data_object ["data"]
|
78
81
|
@data_content_encoding = interpreter.string ["datacontentencoding", "data_content_encoding"]
|
79
82
|
@data_content_type = interpreter.content_type ["datacontenttype", "data_content_type"]
|
80
83
|
@schema_url = interpreter.uri ["schemaurl", "schema_url"]
|
@@ -112,6 +115,8 @@ module CloudEvents
|
|
112
115
|
# event["time"] # => String rfc3339 representation
|
113
116
|
# event.time # => DateTime object
|
114
117
|
#
|
118
|
+
# Results are also always frozen and cannot be modified in place.
|
119
|
+
#
|
115
120
|
# @param key [String,Symbol] The attribute name.
|
116
121
|
# @return [String,nil]
|
117
122
|
#
|
@@ -121,12 +126,12 @@ module CloudEvents
|
|
121
126
|
|
122
127
|
##
|
123
128
|
# Return a hash representation of this event. The returned hash is an
|
124
|
-
# unfrozen copy. Modifications do not affect the original event.
|
129
|
+
# unfrozen deep copy. Modifications do not affect the original event.
|
125
130
|
#
|
126
131
|
# @return [Hash]
|
127
132
|
#
|
128
133
|
def to_h
|
129
|
-
@attributes
|
134
|
+
Utils.deep_dup @attributes
|
130
135
|
end
|
131
136
|
|
132
137
|
##
|
@@ -3,6 +3,9 @@
|
|
3
3
|
require "date"
|
4
4
|
require "uri"
|
5
5
|
|
6
|
+
require "cloud_events/event/field_interpreter"
|
7
|
+
require "cloud_events/event/utils"
|
8
|
+
|
6
9
|
module CloudEvents
|
7
10
|
module Event
|
8
11
|
##
|
@@ -43,7 +46,7 @@ module CloudEvents
|
|
43
46
|
# field.
|
44
47
|
# * **:type** [`String`] - _required_ - The event `type` field.
|
45
48
|
# * **:data** [`Object`] - _optional_ - The data associated with the
|
46
|
-
# event (i.e. the `data` field.
|
49
|
+
# event (i.e. the `data` field).
|
47
50
|
# * **:data_content_type** (or **:datacontenttype**) [`String`,
|
48
51
|
# {ContentType}] - _optional_ - The content-type for the data, if
|
49
52
|
# the data is a string (i.e. the event `datacontenttype` field.)
|
@@ -71,7 +74,7 @@ module CloudEvents
|
|
71
74
|
@id = interpreter.string ["id"], required: true
|
72
75
|
@source = interpreter.uri ["source"], required: true
|
73
76
|
@type = interpreter.string ["type"], required: true
|
74
|
-
@data = interpreter.
|
77
|
+
@data = interpreter.data_object ["data"]
|
75
78
|
@data_content_type = interpreter.content_type ["datacontenttype", "data_content_type"]
|
76
79
|
@data_schema = interpreter.uri ["dataschema", "data_schema"]
|
77
80
|
@subject = interpreter.string ["subject"]
|
@@ -108,6 +111,8 @@ module CloudEvents
|
|
108
111
|
# event["time"] # => String rfc3339 representation
|
109
112
|
# event.time # => DateTime object
|
110
113
|
#
|
114
|
+
# Results are also always frozen and cannot be modified in place.
|
115
|
+
#
|
111
116
|
# @param key [String,Symbol] The attribute name.
|
112
117
|
# @return [String,nil]
|
113
118
|
#
|
@@ -117,12 +122,12 @@ module CloudEvents
|
|
117
122
|
|
118
123
|
##
|
119
124
|
# Return a hash representation of this event. The returned hash is an
|
120
|
-
# unfrozen copy. Modifications do not affect the original event.
|
125
|
+
# unfrozen deep copy. Modifications do not affect the original event.
|
121
126
|
#
|
122
127
|
# @return [Hash]
|
123
128
|
#
|
124
129
|
def to_h
|
125
|
-
@attributes
|
130
|
+
Utils.deep_dup @attributes
|
126
131
|
end
|
127
132
|
|
128
133
|
##
|
@@ -228,21 +228,19 @@ module CloudEvents
|
|
228
228
|
headers = {}
|
229
229
|
body = nil
|
230
230
|
event.to_h.each do |key, value|
|
231
|
-
|
231
|
+
case key
|
232
|
+
when "data"
|
232
233
|
body = value
|
233
|
-
|
234
|
+
when "datacontenttype"
|
234
235
|
headers["Content-Type"] = value
|
235
236
|
else
|
236
237
|
headers["CE-#{key}"] = percent_encode value
|
237
238
|
end
|
238
239
|
end
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
"text/plain; charset=#{body.encoding.name.downcase}"
|
244
|
-
end
|
245
|
-
elsif body.nil?
|
240
|
+
case body
|
241
|
+
when ::String
|
242
|
+
headers["Content-Type"] ||= string_content_type body
|
243
|
+
when nil
|
246
244
|
headers.delete "Content-Type"
|
247
245
|
else
|
248
246
|
body = ::JSON.dump body
|
@@ -288,5 +286,15 @@ module CloudEvents
|
|
288
286
|
end
|
289
287
|
arr.pack "C*"
|
290
288
|
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
def string_content_type str
|
293
|
+
if str.encoding == ::Encoding.ASCII_8BIT
|
294
|
+
"application/octet-stream"
|
295
|
+
else
|
296
|
+
"text/plain; charset=#{str.encoding.name.downcase}"
|
297
|
+
end
|
298
|
+
end
|
291
299
|
end
|
292
300
|
end
|
@@ -137,10 +137,9 @@ module CloudEvents
|
|
137
137
|
structure = event.to_h
|
138
138
|
data = event.data
|
139
139
|
content_type = event.data_content_type
|
140
|
-
if data.is_a?(::String) && !content_type.nil?
|
141
|
-
|
142
|
-
|
143
|
-
end
|
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
|
144
143
|
end
|
145
144
|
structure
|
146
145
|
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.3.0
|
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-03-02 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,6 +28,7 @@ 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/utils.rb
|
31
32
|
- lib/cloud_events/event/v0.rb
|
32
33
|
- lib/cloud_events/event/v1.rb
|
33
34
|
- lib/cloud_events/http_binding.rb
|
@@ -37,10 +38,10 @@ homepage: https://github.com/cloudevents/sdk-ruby
|
|
37
38
|
licenses:
|
38
39
|
- Apache-2.0
|
39
40
|
metadata:
|
40
|
-
changelog_uri: https://cloudevents.github.io/sdk-ruby/v0.
|
41
|
+
changelog_uri: https://cloudevents.github.io/sdk-ruby/v0.3.0/file.CHANGELOG.html
|
41
42
|
source_code_uri: https://github.com/cloudevents/sdk-ruby
|
42
43
|
bug_tracker_uri: https://github.com/cloudevents/sdk-ruby/issues
|
43
|
-
documentation_uri: https://cloudevents.github.io/sdk-ruby/v0.
|
44
|
+
documentation_uri: https://cloudevents.github.io/sdk-ruby/v0.3.0
|
44
45
|
post_install_message:
|
45
46
|
rdoc_options: []
|
46
47
|
require_paths:
|
@@ -49,7 +50,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
50
|
requirements:
|
50
51
|
- - ">="
|
51
52
|
- !ruby/object:Gem::Version
|
52
|
-
version: 2.
|
53
|
+
version: '2.5'
|
53
54
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
55
|
requirements:
|
55
56
|
- - ">="
|