class H2::Server::Stream

Constants

STREAM_DATA_EVENTS

the above take only the event, the following receive both the event and the data

STREAM_EVENTS

each stream event method is wrapped in a block to call a local instance method of the same name

Attributes

complete[R]
connection[R]
push_promises[R]
request[R]
response[R]
stream[R]

Public Class Methods

new(connection:, stream: @closed = false) click to toggle source
# File lib/h2/server/stream.rb, line 29
def initialize connection:, stream:
  @closed        = false
  @completed     = false
  @connection    = connection
  @push_promises = Set.new
  @responded     = false
  @stream        = stream

  bind_events
end

Public Instance Methods

goaway_on_complete() click to toggle source

trigger a GOAWAY frame when this stream is responded to and any/all push promises are complete

# File lib/h2/server/stream.rb, line 110
def goaway_on_complete
  on_complete { connection.goaway }
end
log(level, msg) click to toggle source

logging helper

# File lib/h2/server/stream.rb, line 116
def log level, msg
  Logger.__send__ level, "[stream #{@stream.id}] #{msg}"
end
make_promise(p) click to toggle source

begin the new push promise stream from this +@stream+ by sending the initial headers frame

@see +PushPromise#make_on!+ @see +HTTP2::Stream#promise+

# File lib/h2/server/stream.rb, line 81
def make_promise p
  p.make_on self
  push_promises << p
  p
end
on_complete(&block) click to toggle source

set or call +@complete+ callback

# File lib/h2/server/stream.rb, line 89
def on_complete &block
  return true if @completed
  if block
    @complete = block
  elsif @completed = (@responded and push_promises_complete?)
    @complete[] if Proc === complete
    true
  else
    false
  end
end
push_promise(*args) click to toggle source

create a push promise, send the headers, then queue an asynchronous task on the reactor to deliver the data

# File lib/h2/server/stream.rb, line 60
def push_promise *args
  pp = push_promise_for(*args)
  make_promise pp
  @connection.server.async.handle_push_promise pp
end
push_promise_for(path:, headers: {}) click to toggle source

create a push promise

# File lib/h2/server/stream.rb, line 68
def push_promise_for path:, headers: {}, body: nil
  headers.merge! AUTHORITY_KEY => @request.authority,
                 SCHEME_KEY    => @request.scheme

  PushPromise.new path: path, headers: headers, body: body
end
push_promises_complete?() click to toggle source

check for push promises completion

# File lib/h2/server/stream.rb, line 103
def push_promises_complete?
  @push_promises.empty? or @push_promises.all? {|p| p.kept? or p.canceled?}
end
respond(status:, headers: {}) click to toggle source

write status, headers, and body to +@stream+

# File lib/h2/server/stream.rb, line 42
def respond status:, headers: {}, body: ''
  response = Response.new stream: self,
                          status: status,
                          headers: headers,
                          body: body

  if @closed
    log :warn, 'stream closed before response sent'
  else
    log :info, response
    response.respond_on(stream)
    @responded = true
  end
end
to_eventsource(headers: {}) click to toggle source

make this stream into an SSE event source

raises StreamError if the request's content-type is not valid

@return [H2::Server::Stream::EventSource]

# File lib/h2/server/stream.rb, line 126
def to_eventsource headers: {}
  EventSource.new stream: self, headers: headers
end

Protected Instance Methods

bind_events() click to toggle source

bind parser events to this instance

# File lib/h2/server/stream.rb, line 134
def bind_events
  STREAM_EVENTS.each do |e|
    on = "on_#{e}".to_sym
    @stream.on(e) { __send__ on }
  end
  STREAM_DATA_EVENTS.each do |e|
    on = "on_#{e}".to_sym
    @stream.on(e) { |x| __send__ on, x }
  end
end
on_active() click to toggle source

called by +@stream+ when this stream is activated

# File lib/h2/server/stream.rb, line 147
def on_active
  log :debug, 'active'
  @request = H2::Server::Stream::Request.new self
end
on_close() click to toggle source

called by +@stream+ when this stream is closed

# File lib/h2/server/stream.rb, line 154
def on_close
  log :debug, 'close'
  on_complete
  @closed = true
end
on_data(d) click to toggle source

called by +@stream+ with a String body part

# File lib/h2/server/stream.rb, line 170
def on_data d
  log :debug, "data: <<#{d}>>"
  @request.body << d
end
on_half_close() click to toggle source

called by +@stream+ when body/request is complete, signaling that client is ready for response(s)

# File lib/h2/server/stream.rb, line 178
def on_half_close
  log :debug, 'half_close'
  connection.server.async.handle_stream self
end
on_headers(h) click to toggle source

called by +@stream+ with a Hash

# File lib/h2/server/stream.rb, line 162
def on_headers h
  incoming_headers = Hash[h]
  log :debug, "headers: #{incoming_headers}"
  @request.headers.merge! incoming_headers
end