ld-eventsource 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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