ld-eventsource 2.1.1 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14623ca76eeb863804646a598dec0a4f368bdd4fbf8875b7d5bb1be62c1845bd
4
- data.tar.gz: 9c9d521d4e10f01f93f04431acfbbe2821434e99dd2738c09726827a84a96ed2
3
+ metadata.gz: 76ed80d3fefe60b6a147769dc1b44b0dfd7fe5b6841ff84655ae86764def70b9
4
+ data.tar.gz: cf24cff61716e4487d74023e09be18a516232a198aabcda2742fb8ec8de9de72
5
5
  SHA512:
6
- metadata.gz: 4fccea73f41283286656e7a8ad8d10c72e0175b68a34499008d38d897d9a8828000d3f9cdb582dca682e182d1d0045240d0522fd9e28e72401410aad668a603d
7
- data.tar.gz: c0756a730b152c06e7a1497703d1acdc0216a9ad8938798914fda239011d34d4c5bf521d51f3cf4f06829e6830befb550d9a47bf6d9fa19bda9ee3e2ba08972b
6
+ metadata.gz: 329c044114376d9d618e37a138b7c99dc5c4f00baa3d22ea72ce88309deec8bd22a62c0513a362223542f9ddfa5aaae0413e14bbf336ef943a90e0374d2d9c89
7
+ data.tar.gz: 9110b5daa08a3c7fb04bb432527feaf4bee5e67d02b215621c89546ffd0a4da98c14a9618cdf4040474afe1649db777996547bfb502512930a3b364f05dd57c1
@@ -306,6 +306,9 @@ module SSE
306
306
  else
307
307
  begin
308
308
  data = cxn.readpartial
309
+ # readpartial gives us a string, which may not be a valid UTF-8 string because a
310
+ # multi-byte character might not yet have been fully read, but BufferedLineReader
311
+ # will handle that.
309
312
  rescue HTTP::TimeoutError
310
313
  # For historical reasons, we rethrow this as our own type
311
314
  raise Errors::ReadTimeoutError.new(@read_timeout)
@@ -315,7 +318,7 @@ module SSE
315
318
  end
316
319
  end
317
320
  end
318
- event_parser = Impl::EventParser.new(Impl::BufferedLineReader.lines_from(chunks))
321
+ event_parser = Impl::EventParser.new(Impl::BufferedLineReader.lines_from(chunks), @last_id)
319
322
 
320
323
  event_parser.items.each do |item|
321
324
  return if @stopped.value
@@ -331,7 +334,7 @@ module SSE
331
334
 
332
335
  def dispatch_event(event)
333
336
  @logger.debug { "Received event: #{event}" }
334
- @last_id = event.id
337
+ @last_id = event.id if !event.id.nil?
335
338
 
336
339
  # Pass the event to the caller
337
340
  @on[:event].call(event)
@@ -354,7 +357,7 @@ module SSE
354
357
  'Cache-Control' => 'no-cache',
355
358
  'User-Agent' => 'ruby-eventsource'
356
359
  }
357
- h['Last-Event-Id'] = @last_id if !@last_id.nil?
360
+ h['Last-Event-Id'] = @last_id if !@last_id.nil? && @last_id != ""
358
361
  h.merge(@headers)
359
362
  end
360
363
  end
@@ -11,6 +11,10 @@ module SSE
11
11
  # if there were multiple `data:` lines, they are concatenated with newlines
12
12
  # @!attribute id
13
13
  # @return [String] the string that appeared after `id:` in the stream if any, or nil
14
+ # @!attribute last_event_id
15
+ # @return [String] the `id:` value that was most recently seen in an event from
16
+ # this stream; this differs from the `id` property in that it retains the same value
17
+ # in subsequent events if they do not provide their own `id:`
14
18
  #
15
- StreamEvent = Struct.new(:type, :data, :id)
19
+ StreamEvent = Struct.new(:type, :data, :id, :last_event_id)
16
20
  end
@@ -41,7 +41,11 @@ module SSE
41
41
  @last_good_time = nil
42
42
  target = ([@base_interval * (2 ** @attempts), @max_interval].min).to_f
43
43
  @attempts += 1
44
- (target / 2) + @jitter_rand.rand(target / 2)
44
+ if target == 0
45
+ 0 # in some Ruby versions it's illegal to call rand(0)
46
+ else
47
+ (target / 2) + @jitter_rand.rand(target / 2)
48
+ end
45
49
  end
46
50
 
47
51
  #
@@ -9,17 +9,21 @@ module SSE
9
9
  # input data runs out, the output enumerator ends and does not include any partially
10
10
  # completed line.
11
11
  #
12
- # @param [Enumerator] chunks an enumerator that will yield strings from a stream
13
- # @return [Enumerator] an enumerator that will yield one line at a time
12
+ # @param [Enumerator] chunks an enumerator that will yield strings from a stream -
13
+ # these are treated as raw UTF-8 bytes, regardless of the string's declared encoding
14
+ # (so it is OK if a multi-byte character is split across chunks); if the declared
15
+ # encoding of the chunk is not ASCII-8BIT, it will be changed to ASCII-8BIT in place
16
+ # @return [Enumerator] an enumerator that will yield one line at a time in UTF-8
14
17
  #
15
18
  def self.lines_from(chunks)
16
- buffer = ""
19
+ buffer = "".b
17
20
  position = 0
18
21
  line_start = 0
19
22
  last_char_was_cr = false
20
23
 
21
24
  Enumerator.new do |gen|
22
25
  chunks.each do |chunk|
26
+ chunk.force_encoding("ASCII-8BIT")
23
27
  buffer << chunk
24
28
 
25
29
  loop do
@@ -47,7 +51,12 @@ module SSE
47
51
  next
48
52
  end
49
53
 
50
- line = buffer[line_start, i - line_start]
54
+ line = buffer[line_start, i - line_start].force_encoding("UTF-8")
55
+ # Calling force_encoding just declares that we believe the encoding of this string to be
56
+ # UTF-8 (which is the only encoding allowed in the SSE protocol); it doesn't cause any
57
+ # re-decoding of the string. The previous line-parsing steps were done on raw 8-bit
58
+ # strings so that it won't try to do any UTF-8 decoding on intermediate slices.
59
+
51
60
  last_char_was_cr = false
52
61
  i += 1
53
62
  if ch == "\r"
@@ -23,8 +23,9 @@ module SSE
23
23
  # @param [Enumerator] lines an enumerator that will yield one line of text at a time;
24
24
  # the lines should not include line terminators
25
25
  #
26
- def initialize(lines)
26
+ def initialize(lines, last_event_id = nil)
27
27
  @lines = lines
28
+ @last_event_id = last_event_id
28
29
  reset_buffers
29
30
  end
30
31
 
@@ -65,7 +66,10 @@ module SSE
65
66
  @data << value
66
67
  @have_data = true
67
68
  when "id"
68
- @id = value
69
+ if !value.include?("\x00")
70
+ @id = value
71
+ @last_event_id = value
72
+ end
69
73
  when "retry"
70
74
  if /^(?<num>\d+)$/ =~ value
71
75
  return SetRetryInterval.new(num.to_i)
@@ -76,7 +80,7 @@ module SSE
76
80
 
77
81
  def maybe_create_event
78
82
  return nil if !@have_data
79
- StreamEvent.new(@type || :message, @data, @id)
83
+ StreamEvent.new(@type || :message, @data, @id, @last_event_id)
80
84
  end
81
85
  end
82
86
  end
@@ -1,3 +1,3 @@
1
1
  module SSE
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ld-eventsource
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-12 00:00:00.000000000 Z
11
+ date: 2021-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  requirements: []
139
- rubygems_version: 3.2.29
139
+ rubygems_version: 3.3.4
140
140
  signing_key:
141
141
  specification_version: 4
142
142
  summary: LaunchDarkly SSE client