cloud_events 0.7.1 → 0.8.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.
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "base64"
4
3
  require "json"
5
4
 
6
5
  module CloudEvents
@@ -80,7 +79,7 @@ module CloudEvents
80
79
  # @return [Hash] if accepting the request and returning a result
81
80
  # @return [nil] if declining the request.
82
81
  #
83
- def decode_event **_kwargs
82
+ def decode_event(**_kwargs)
84
83
  nil
85
84
  end
86
85
 
@@ -117,7 +116,7 @@ module CloudEvents
117
116
  # @return [Hash] if accepting the request and returning a result
118
117
  # @return [nil] if declining the request.
119
118
  #
120
- def encode_event **_kwargs
119
+ def encode_event(**_kwargs)
121
120
  nil
122
121
  end
123
122
 
@@ -156,7 +155,7 @@ module CloudEvents
156
155
  # @return [Hash] if accepting the request and returning a result
157
156
  # @return [nil] if declining the request.
158
157
  #
159
- def decode_data **_kwargs
158
+ def decode_data(**_kwargs)
160
159
  nil
161
160
  end
162
161
 
@@ -195,7 +194,7 @@ module CloudEvents
195
194
  # @return [Hash] if accepting the request and returning a result
196
195
  # @return [nil] if declining the request.
197
196
  #
198
- def encode_data **_kwargs
197
+ def encode_data(**_kwargs)
199
198
  nil
200
199
  end
201
200
 
@@ -213,7 +212,7 @@ module CloudEvents
213
212
  # format's result as an argument, and returns either the result to
214
213
  # indicate acceptability, or `nil` to indicate not.
215
214
  #
216
- def initialize formats = [], &result_checker
215
+ def initialize(formats = [], &result_checker)
217
216
  @formats = formats
218
217
  @result_checker = result_checker
219
218
  end
@@ -228,10 +227,10 @@ module CloudEvents
228
227
  ##
229
228
  # Implements {Format#decode_event}
230
229
  #
231
- def decode_event **kwargs
230
+ def decode_event(**kwargs)
232
231
  @formats.each do |elem|
233
232
  result = elem.decode_event(**kwargs)
234
- result = @result_checker.call result if @result_checker
233
+ result = @result_checker.call(result) if @result_checker
235
234
  return result if result
236
235
  end
237
236
  nil
@@ -240,10 +239,10 @@ module CloudEvents
240
239
  ##
241
240
  # Implements {Format#encode_event}
242
241
  #
243
- def encode_event **kwargs
242
+ def encode_event(**kwargs)
244
243
  @formats.each do |elem|
245
244
  result = elem.encode_event(**kwargs)
246
- result = @result_checker.call result if @result_checker
245
+ result = @result_checker.call(result) if @result_checker
247
246
  return result if result
248
247
  end
249
248
  nil
@@ -252,10 +251,10 @@ module CloudEvents
252
251
  ##
253
252
  # Implements {Format#decode_data}
254
253
  #
255
- def decode_data **kwargs
254
+ def decode_data(**kwargs)
256
255
  @formats.each do |elem|
257
256
  result = elem.decode_data(**kwargs)
258
- result = @result_checker.call result if @result_checker
257
+ result = @result_checker.call(result) if @result_checker
259
258
  return result if result
260
259
  end
261
260
  nil
@@ -264,10 +263,10 @@ module CloudEvents
264
263
  ##
265
264
  # Implements {Format#encode_data}
266
265
  #
267
- def encode_data **kwargs
266
+ def encode_data(**kwargs)
268
267
  @formats.each do |elem|
269
268
  result = elem.encode_data(**kwargs)
270
- result = @result_checker.call result if @result_checker
269
+ result = @result_checker.call(result) if @result_checker
271
270
  return result if result
272
271
  end
273
272
  nil
@@ -31,7 +31,7 @@ module CloudEvents
31
31
  def self.default
32
32
  @default ||= begin
33
33
  http_binding = new
34
- http_binding.register_formatter JsonFormat.new, encoder_name: JSON_FORMAT
34
+ http_binding.register_formatter(JsonFormat.new, encoder_name: JSON_FORMAT)
35
35
  http_binding.default_encoder_name = JSON_FORMAT
36
36
  http_binding
37
37
  end
@@ -46,14 +46,14 @@ module CloudEvents
46
46
  end
47
47
  @event_encoders = {}
48
48
  @data_decoders = Format::Multi.new do |result|
49
- result&.key?(:data) && result&.key?(:content_type) ? result : nil
49
+ result&.key?(:data) && result.key?(:content_type) ? result : nil
50
50
  end
51
51
  @data_encoders = Format::Multi.new do |result|
52
- result&.key?(:content) && result&.key?(:content_type) ? result : nil
52
+ result&.key?(:content) && result.key?(:content_type) ? result : nil
53
53
  end
54
54
  text_format = TextFormat.new
55
- @data_decoders.formats.replace [text_format, DefaultDataFormat]
56
- @data_encoders.formats.replace [text_format, DefaultDataFormat]
55
+ @data_decoders.formats.replace([text_format, DefaultDataFormat])
56
+ @data_encoders.formats.replace([text_format, DefaultDataFormat])
57
57
 
58
58
  @default_encoder_name = nil
59
59
  end
@@ -71,18 +71,18 @@ module CloudEvents
71
71
  # and will be removed in version 1.0. Use encoder_name instead.
72
72
  # @return [self]
73
73
  #
74
- def register_formatter formatter, deprecated_name = nil, encoder_name: nil
74
+ def register_formatter(formatter, deprecated_name = nil, encoder_name: nil)
75
75
  encoder_name ||= deprecated_name
76
76
  encoder_name = encoder_name.to_s.strip.downcase if encoder_name
77
- decode_event = formatter.respond_to? :decode_event
78
- encode_event = encoder_name if formatter.respond_to? :encode_event
79
- decode_data = formatter.respond_to? :decode_data
80
- encode_data = formatter.respond_to? :encode_data
81
- register_formatter_methods formatter,
77
+ decode_event = formatter.respond_to?(:decode_event)
78
+ encode_event = encoder_name if formatter.respond_to?(:encode_event)
79
+ decode_data = formatter.respond_to?(:decode_data)
80
+ encode_data = formatter.respond_to?(:encode_data)
81
+ register_formatter_methods(formatter,
82
82
  decode_event: decode_event,
83
83
  encode_event: encode_event,
84
84
  decode_data: decode_data,
85
- encode_data: encode_data
85
+ encode_data: encode_data)
86
86
  self
87
87
  end
88
88
 
@@ -102,20 +102,20 @@ module CloudEvents
102
102
  # {CloudEvents::Format#encode_data} method.
103
103
  # @return [self]
104
104
  #
105
- def register_formatter_methods formatter,
105
+ def register_formatter_methods(formatter,
106
106
  decode_event: false,
107
107
  encode_event: nil,
108
108
  decode_data: false,
109
- encode_data: false
110
- @event_decoders.formats.unshift formatter if decode_event
109
+ encode_data: false)
110
+ @event_decoders.formats.unshift(formatter) if decode_event
111
111
  if encode_event
112
112
  encoders = @event_encoders[encode_event] ||= Format::Multi.new do |result|
113
- result&.key?(:content) && result&.key?(:content_type) ? result : nil
113
+ result&.key?(:content) && result.key?(:content_type) ? result : nil
114
114
  end
115
- encoders.formats.unshift formatter
115
+ encoders.formats.unshift(formatter)
116
116
  end
117
- @data_decoders.formats.unshift formatter if decode_data
118
- @data_encoders.formats.unshift formatter if encode_data
117
+ @data_decoders.formats.unshift(formatter) if decode_data
118
+ @data_encoders.formats.unshift(formatter) if encode_data
119
119
  self
120
120
  end
121
121
 
@@ -136,10 +136,10 @@ module CloudEvents
136
136
  # @param env [Hash] The Rack environment.
137
137
  # @return [boolean] Whether the request is likely a CloudEvent.
138
138
  #
139
- def probable_event? env
140
- return false if ILLEGAL_METHODS.include? env["REQUEST_METHOD"]
139
+ def probable_event?(env)
140
+ return false if ILLEGAL_METHODS.include?(env["REQUEST_METHOD"])
141
141
  return true if env["HTTP_CE_SPECVERSION"]
142
- content_type = ContentType.new env["CONTENT_TYPE"].to_s
142
+ content_type = ContentType.new(env["CONTENT_TYPE"].to_s)
143
143
  content_type.media_type == "application" &&
144
144
  ["cloudevents", "cloudevents-batch"].include?(content_type.subtype_base)
145
145
  end
@@ -166,17 +166,17 @@ module CloudEvents
166
166
  # @raise [CloudEvents::CloudEventsError] if an event could not be decoded
167
167
  # from the request.
168
168
  #
169
- def decode_event env, allow_opaque: false, **format_args
169
+ def decode_event(env, allow_opaque: false, **format_args)
170
170
  request_method = env["REQUEST_METHOD"]
171
- raise NotCloudEventError, "Request method is #{request_method}" if ILLEGAL_METHODS.include? request_method
171
+ raise(NotCloudEventError, "Request method is #{request_method}") if ILLEGAL_METHODS.include?(request_method)
172
172
  content_type_string = env["CONTENT_TYPE"]
173
- content_type = ContentType.new content_type_string if content_type_string
174
- content = read_with_charset env["rack.input"], content_type&.charset
173
+ content_type = ContentType.new(content_type_string) if content_type_string
174
+ content = read_with_charset(env["rack.input"], content_type&.charset)
175
175
  result = decode_binary_content(content, content_type, env, false, **format_args) ||
176
176
  decode_structured_content(content, content_type, allow_opaque, **format_args)
177
177
  if result.nil?
178
178
  content_type_string = content_type_string ? content_type_string.inspect : "not present"
179
- raise NotCloudEventError, "Content-Type is #{content_type_string}, and CE-SpecVersion is not present"
179
+ raise(NotCloudEventError, "Content-Type is #{content_type_string}, and CE-SpecVersion is not present")
180
180
  end
181
181
  result
182
182
  end
@@ -204,24 +204,24 @@ module CloudEvents
204
204
  # @param format_args [keywords] Extra args to pass to the formatter.
205
205
  # @return [Array(headers,String)]
206
206
  #
207
- def encode_event event, structured_format: false, **format_args
208
- if event.is_a? Event::Opaque
207
+ def encode_event(event, structured_format: false, **format_args)
208
+ if event.is_a?(Event::Opaque)
209
209
  [{ "Content-Type" => event.content_type.to_s }, event.content]
210
210
  elsif !structured_format
211
- if event.is_a? ::Array
212
- raise ::ArgumentError, "Encoding a batch requires structured_format"
211
+ if event.is_a?(::Array)
212
+ raise(::ArgumentError, "Encoding a batch requires structured_format")
213
213
  end
214
- encode_binary_content event, legacy_data_encode: false, **format_args
214
+ encode_binary_content(event, legacy_data_encode: false, **format_args)
215
215
  else
216
216
  structured_format = default_encoder_name if structured_format == true
217
- raise ::ArgumentError, "Format name not specified, and no default is set" unless structured_format
217
+ raise(::ArgumentError, "Format name not specified, and no default is set") unless structured_format
218
218
  case event
219
219
  when ::Array
220
- encode_batched_content event, structured_format, **format_args
220
+ encode_batched_content(event, structured_format, **format_args)
221
221
  when Event
222
- encode_structured_content event, structured_format, **format_args
222
+ encode_structured_content(event, structured_format, **format_args)
223
223
  else
224
- raise ::ArgumentError, "Unknown event type: #{event.class}"
224
+ raise(::ArgumentError, "Unknown event type: #{event.class}")
225
225
  end
226
226
  end
227
227
  end
@@ -243,10 +243,10 @@ module CloudEvents
243
243
  # @raise [CloudEvents::CloudEventsError] if the request appears to be a
244
244
  # CloudEvent but decoding failed.
245
245
  #
246
- def decode_rack_env env, **format_args
246
+ def decode_rack_env(env, **format_args)
247
247
  content_type_string = env["CONTENT_TYPE"]
248
- content_type = ContentType.new content_type_string if content_type_string
249
- content = read_with_charset env["rack.input"], content_type&.charset
248
+ content_type = ContentType.new(content_type_string) if content_type_string
249
+ content = read_with_charset(env["rack.input"], content_type&.charset)
250
250
  env["rack.input"].rewind rescue nil
251
251
  decode_binary_content(content, content_type, env, true, **format_args) ||
252
252
  decode_structured_content(content, content_type, false, **format_args)
@@ -262,12 +262,12 @@ module CloudEvents
262
262
  # @param format_args [keywords] Extra args to pass to the formatter.
263
263
  # @return [Array(headers,String)]
264
264
  #
265
- def encode_structured_content event, format_name, **format_args
266
- result = @event_encoders[format_name]&.encode_event event: event,
265
+ def encode_structured_content(event, format_name, **format_args)
266
+ result = @event_encoders[format_name]&.encode_event(event: event,
267
267
  data_encoder: @data_encoders,
268
- **format_args
268
+ **format_args)
269
269
  return [{ "Content-Type" => result[:content_type].to_s }, result[:content]] if result
270
- raise ::ArgumentError, "Unknown format name: #{format_name.inspect}"
270
+ raise(::ArgumentError, "Unknown format name: #{format_name.inspect}")
271
271
  end
272
272
 
273
273
  ##
@@ -280,12 +280,12 @@ module CloudEvents
280
280
  # @param format_args [keywords] Extra args to pass to the formatter.
281
281
  # @return [Array(headers,String)]
282
282
  #
283
- def encode_batched_content event_batch, format_name, **format_args
284
- result = @event_encoders[format_name]&.encode_event event_batch: event_batch,
283
+ def encode_batched_content(event_batch, format_name, **format_args)
284
+ result = @event_encoders[format_name]&.encode_event(event_batch: event_batch,
285
285
  data_encoder: @data_encoders,
286
- **format_args
286
+ **format_args)
287
287
  return [{ "Content-Type" => result[:content_type].to_s }, result[:content]] if result
288
- raise ::ArgumentError, "Unknown format name: #{format_name.inspect}"
288
+ raise(::ArgumentError, "Unknown format name: #{format_name.inspect}")
289
289
  end
290
290
 
291
291
  ##
@@ -297,18 +297,18 @@ module CloudEvents
297
297
  # @param format_args [keywords] Extra args to pass to the formatter.
298
298
  # @return [Array(headers,String)]
299
299
  #
300
- def encode_binary_content event, legacy_data_encode: true, **format_args
300
+ def encode_binary_content(event, legacy_data_encode: true, **format_args)
301
301
  headers = {}
302
302
  event.to_h.each do |key, value|
303
- unless ["data", "data_encoded", "datacontenttype"].include? key
304
- headers["CE-#{key}"] = percent_encode value
303
+ unless ["data", "data_encoded", "datacontenttype"].include?(key)
304
+ headers["CE-#{key}"] = percent_encode(value)
305
305
  end
306
306
  end
307
307
  body, content_type =
308
308
  if legacy_data_encode || event.spec_version.start_with?("0.")
309
- legacy_extract_event_data event
309
+ legacy_extract_event_data(event)
310
310
  else
311
- normal_extract_event_data event, format_args
311
+ normal_extract_event_data(event, format_args)
312
312
  end
313
313
  headers["Content-Type"] = content_type.to_s if content_type
314
314
  [headers, body]
@@ -323,10 +323,10 @@ module CloudEvents
323
323
  # cycle of percent-encoding.
324
324
  # @return [String] Resulting decoded string in UTF-8.
325
325
  #
326
- def percent_decode str
326
+ def percent_decode(str)
327
327
  str = str.gsub(/"((?:[^"\\]|\\.)*)"/) { ::Regexp.last_match(1).gsub(/\\(.)/, '\1') }
328
- decoded_str = str.gsub(/%[0-9a-fA-F]{2}/) { |m| [m[1..-1].to_i(16)].pack "C" }
329
- decoded_str.force_encoding ::Encoding::UTF_8
328
+ decoded_str = str.gsub(/%[0-9a-fA-F]{2}/) { |m| [m[1..].to_i(16)].pack("C") }
329
+ decoded_str.force_encoding(::Encoding::UTF_8)
330
330
  end
331
331
 
332
332
  ##
@@ -340,9 +340,9 @@ module CloudEvents
340
340
  # in UTF-8.
341
341
  # @return [String] Resulting encoded string in ASCII.
342
342
  #
343
- def percent_encode str
343
+ def percent_encode(str)
344
344
  arr = []
345
- utf_str = str.to_s.encode ::Encoding::UTF_8
345
+ utf_str = str.to_s.encode(::Encoding::UTF_8)
346
346
  utf_str.each_byte do |byte|
347
347
  if byte >= 33 && byte <= 126 && byte != 34 && byte != 37
348
348
  arr << byte
@@ -354,31 +354,31 @@ module CloudEvents
354
354
  arr << 37 << hi << lo
355
355
  end
356
356
  end
357
- arr.pack "C*"
357
+ arr.pack("C*")
358
358
  end
359
359
 
360
360
  private
361
361
 
362
- def add_named_formatter collection, formatter, name
362
+ def add_named_formatter(collection, formatter, name)
363
363
  return unless name
364
364
  formatters = collection[name] ||= []
365
- formatters.unshift formatter unless formatters.include? formatter
365
+ formatters.unshift(formatter) unless formatters.include?(formatter)
366
366
  end
367
367
 
368
368
  ##
369
369
  # Decode a single event from the given request body and content type in
370
370
  # structured mode.
371
371
  #
372
- def decode_structured_content content, content_type, allow_opaque, **format_args
373
- result = @event_decoders.decode_event content: content,
372
+ def decode_structured_content(content, content_type, allow_opaque, **format_args)
373
+ result = @event_decoders.decode_event(content: content,
374
374
  content_type: content_type,
375
375
  data_decoder: @data_decoders,
376
- **format_args
376
+ **format_args)
377
377
  return result[:event] || result[:event_batch] if result
378
378
  if content_type&.media_type == "application" &&
379
379
  ["cloudevents", "cloudevents-batch"].include?(content_type.subtype_base)
380
- return Event::Opaque.new content, content_type if allow_opaque
381
- raise UnsupportedFormatError, "Unknown cloudevents content type: #{content_type}"
380
+ return Event::Opaque.new(content, content_type) if allow_opaque
381
+ raise(UnsupportedFormatError, "Unknown cloudevents content type: #{content_type}")
382
382
  end
383
383
  nil
384
384
  end
@@ -389,33 +389,33 @@ module CloudEvents
389
389
  # TODO: legacy_data_decode is deprecated and can be removed when
390
390
  # decode_rack_env is removed.
391
391
  #
392
- def decode_binary_content content, content_type, env, legacy_data_decode, **format_args
392
+ def decode_binary_content(content, content_type, env, legacy_data_decode, **format_args)
393
393
  spec_version = env["HTTP_CE_SPECVERSION"]
394
394
  return nil unless spec_version
395
395
  unless spec_version =~ /^0\.3|1(\.|$)/
396
- raise SpecVersionError, "Unrecognized specversion: #{spec_version}"
396
+ raise(SpecVersionError, "Unrecognized specversion: #{spec_version}")
397
397
  end
398
398
  attributes = { "spec_version" => spec_version }
399
399
  if legacy_data_decode || spec_version.start_with?("0.")
400
- legacy_populate_data_attributes attributes, content, content_type
400
+ legacy_populate_data_attributes(attributes, content, content_type)
401
401
  else
402
- normal_populate_data_attributes attributes, content, content_type, spec_version, format_args
402
+ normal_populate_data_attributes(attributes, content, content_type, spec_version, format_args)
403
403
  end
404
- populate_attributes_from_env attributes, env
405
- Event.create spec_version: spec_version, set_attributes: attributes
404
+ populate_attributes_from_env(attributes, env)
405
+ Event.create(spec_version: spec_version, set_attributes: attributes)
406
406
  end
407
407
 
408
- def legacy_populate_data_attributes attributes, content, content_type
408
+ def legacy_populate_data_attributes(attributes, content, content_type)
409
409
  attributes["data"] = content
410
410
  attributes["data_content_type"] = content_type if content_type
411
411
  end
412
412
 
413
- def normal_populate_data_attributes attributes, content, content_type, spec_version, format_args
413
+ def normal_populate_data_attributes(attributes, content, content_type, spec_version, format_args)
414
414
  attributes["data_encoded"] = content
415
- result = @data_decoders.decode_data spec_version: spec_version,
415
+ result = @data_decoders.decode_data(spec_version: spec_version,
416
416
  content: content,
417
417
  content_type: content_type,
418
- **format_args
418
+ **format_args)
419
419
  if result
420
420
  attributes["data"] = result[:data]
421
421
  content_type = result[:content_type]
@@ -423,17 +423,17 @@ module CloudEvents
423
423
  attributes["data_content_type"] = content_type if content_type
424
424
  end
425
425
 
426
- def populate_attributes_from_env attributes, env
426
+ def populate_attributes_from_env(attributes, env)
427
427
  omit_names = ["specversion", "spec_version", "data", "datacontenttype", "data_content_type"]
428
428
  env.each do |key, value|
429
- match = /^HTTP_CE_(\w+)$/.match key
429
+ match = /^HTTP_CE_(\w+)$/.match(key)
430
430
  next unless match
431
431
  attr_name = match[1].downcase
432
- attributes[attr_name] = percent_decode value unless omit_names.include? attr_name
432
+ attributes[attr_name] = percent_decode(value) unless omit_names.include?(attr_name)
433
433
  end
434
434
  end
435
435
 
436
- def legacy_extract_event_data event
436
+ def legacy_extract_event_data(event)
437
437
  body = event.data
438
438
  content_type = event.data_content_type&.to_s
439
439
  case body
@@ -446,31 +446,31 @@ module CloudEvents
446
446
  end
447
447
  end
448
448
 
449
- def normal_extract_event_data event, format_args
449
+ def normal_extract_event_data(event, format_args)
450
450
  body = event.data_encoded
451
451
  if body
452
452
  [body, event.data_content_type]
453
453
  elsif event.data?
454
- result = @data_encoders.encode_data spec_version: event.spec_version,
454
+ result = @data_encoders.encode_data(spec_version: event.spec_version,
455
455
  data: event.data,
456
456
  content_type: event.data_content_type,
457
- **format_args
458
- raise UnsupportedFormatError, "Could not encode unknown content-type: #{content_type}" unless result
457
+ **format_args)
458
+ raise(UnsupportedFormatError, "Could not encode unknown content-type: #{content_type}") unless result
459
459
  [result[:content], result[:content_type]]
460
460
  else
461
461
  ["", nil]
462
462
  end
463
463
  end
464
464
 
465
- def read_with_charset io, charset
465
+ def read_with_charset(io, charset)
466
466
  return nil if io.nil?
467
467
  str = io.read
468
468
  if charset
469
469
  begin
470
- str.force_encoding charset
470
+ str.force_encoding(charset)
471
471
  rescue ::ArgumentError
472
472
  # Use binary for now if the charset is unrecognized
473
- str.force_encoding ::Encoding::ASCII_8BIT
473
+ str.force_encoding(::Encoding::ASCII_8BIT)
474
474
  end
475
475
  end
476
476
  str
@@ -479,13 +479,13 @@ module CloudEvents
479
479
  # @private
480
480
  module DefaultDataFormat
481
481
  # @private
482
- def self.decode_data content: nil, content_type: nil, **_extra_kwargs
482
+ def self.decode_data(content: nil, content_type: nil, **_extra_kwargs)
483
483
  return nil unless content_type.nil?
484
484
  { data: content, content_type: nil }
485
485
  end
486
486
 
487
487
  # @private
488
- def self.encode_data data: nil, content_type: nil, **_extra_kwargs
488
+ def self.encode_data(data: nil, content_type: nil, **_extra_kwargs)
489
489
  return nil unless content_type.nil?
490
490
  { content: data.to_s, content_type: nil }
491
491
  end