Module: Sinatra::SSE::Marshal
- Included in:
- Sinatra::SSE
- Defined in:
- lib/sinatra/sse/marshal.rb
Overview
packing/unpacking SSE events
Constant Summary collapse
- FIXED_ORDER =
{ :event => 1, :id => 2, :data => 3 }
Instance Method Summary collapse
-
#marshal(object) ⇒ Object
converts an object into an event.
-
#unmarshal(data) ⇒ Object
Unmarshals a single event in data.
-
#unmarshal_all(data) ⇒ Object
Extract all events from a data stream.
Instance Method Details
#marshal(object) ⇒ Object
converts an object into an event.
The object must be a hash or a String.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/sinatra/sse/marshal.rb', line 20 def marshal(object) expect! object => [ String, Hash ] if object.is_a?(String) object = { :data => object } end # sort all entries in a way, that make sure that event, id, data # are at the end. This makes sure that confirming clients just # ignore the extra entries. If we would just send them in random # order we might produce "bogus" events, when "data", "event", # and "id" are separated by invalid entries. entries = object.sort_by { |key, value| FIXED_ORDER[key.to_sym] || 0 } entries.map do |key, value| escaped_value = value.gsub(/(\r\n|\r|\n)/, "\n#{key}: ") "#{key}: #{escaped_value}\n" end.join + "\n" end |
#unmarshal(data) ⇒ Object
Unmarshals a single event in data. The string SHOULD NOT contain multipe events, or else the returned hash somehow mangles all these events into a single one.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/sinatra/sse/marshal.rb', line 43 def unmarshal(data) event = Hash.new { |hash, key| hash[key] = [] } data.split("\n").each do |line| key, value = line.split(/: ?/, 2) next if key =~ /^\s*$/ event[key.to_sym] << value end event.inject({}) do |hash, (key, value)| hash.update key => value.join("\n") end end |
#unmarshal_all(data) ⇒ Object
Extract all events from a data stream.
59 60 61 62 63 |
# File 'lib/sinatra/sse/marshal.rb', line 59 def unmarshal_all(data) data.split(/\n\n/). map { |event| unpack(event) }. reject(&:empty?) end |