Class: H2::Server::Stream

Inherits:
Object
  • Object
show all
Defined in:
lib/h2/server/stream.rb,
lib/h2/server/stream/request.rb,
lib/h2/server/stream/response.rb,
lib/h2/server/stream/event_source.rb

Defined Under Namespace

Classes: EventSource, Request, Response

Constant Summary collapse

STREAM_EVENTS =

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

[
  :active,
  :close,
  :half_close
]
STREAM_DATA_EVENTS =

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

[
  :headers,
  :data
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection:, stream:) ⇒ Stream

Returns a new instance of Stream.



33
34
35
36
37
38
39
40
41
42
# File 'lib/h2/server/stream.rb', line 33

def initialize connection:, stream:
  @closed        = false
  @completed     = false
  @connection    = connection
  @push_promises = Set.new
  @responded     = false
  @stream        = stream

  bind_events
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



27
28
29
# File 'lib/h2/server/stream.rb', line 27

def connection
  @connection
end

#push_promisesObject (readonly)

Returns the value of attribute push_promises.



27
28
29
# File 'lib/h2/server/stream.rb', line 27

def push_promises
  @push_promises
end

#requestObject (readonly)

Returns the value of attribute request.



27
28
29
# File 'lib/h2/server/stream.rb', line 27

def request
  @request
end

#responseObject (readonly)

Returns the value of attribute response.



27
28
29
# File 'lib/h2/server/stream.rb', line 27

def response
  @response
end

#streamObject (readonly)

Returns the value of attribute stream.



27
28
29
# File 'lib/h2/server/stream.rb', line 27

def stream
  @stream
end

Instance Method Details

#goaway_on_completeObject

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



114
115
116
# File 'lib/h2/server/stream.rb', line 114

def goaway_on_complete
  on_complete { connection.goaway }
end

#log(level, msg) ⇒ Object

logging helper



120
121
122
# File 'lib/h2/server/stream.rb', line 120

def log level, msg
  Logger.__send__ level, "[stream #{@stream.id}] #{msg}"
end

#make_promise(p) ⇒ Object

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

See Also:

  • H2::Server::Stream.+PushPromise+PushPromise#make_on!+
  • H2::Server::Stream.+HTTP2+HTTP2::Stream+HTTP2::Stream#promise+


85
86
87
88
89
# File 'lib/h2/server/stream.rb', line 85

def make_promise p
  p.make_on self
  push_promises << p
  p
end

#on_complete(&block) ⇒ Object

set or call @complete callback



93
94
95
96
97
98
99
100
101
102
103
# File 'lib/h2/server/stream.rb', line 93

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) ⇒ Object

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



64
65
66
67
68
# File 'lib/h2/server/stream.rb', line 64

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: {}, body: nil) ⇒ Object

create a push promise



72
73
74
75
76
77
# File 'lib/h2/server/stream.rb', line 72

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?Boolean

check for push promises completion

Returns:

  • (Boolean)


107
108
109
# File 'lib/h2/server/stream.rb', line 107

def push_promises_complete?
  @push_promises.empty? or @push_promises.all? {|p| p.kept? or p.canceled?}
end

#respond(status:, headers: {}, body: '') ⇒ Object

write status, headers, and body to @stream



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/h2/server/stream.rb', line 46

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: {}) ⇒ H2::Server::Stream::EventSource

make this stream into an SSE event source

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



130
131
132
# File 'lib/h2/server/stream.rb', line 130

def to_eventsource headers: {}
  EventSource.new stream: self, headers: headers
end