Class: HTTP2::Server

Inherits:
Connection show all
Defined in:
lib/http/2/server.rb

Overview

HTTP 2.0 server connection class that implements appropriate header compression / decompression algorithms and stream management logic.

Your code is responsible for feeding request data to the server object, which in turn performs all of the necessary HTTP 2.0 decoding / encoding, state management, and the rest. A simple example:

Examples:

socket = YourTransport.new

conn = HTTP2::Server.new
conn.on(:stream) do |stream|
  ...
end

while bytes = socket.read
  conn << bytes
end

Instance Attribute Summary

Attributes inherited from Connection

#active_stream_count, #local_settings, #local_window, #pending_settings, #remote_settings, #remote_window, #state

Instance Method Summary collapse

Methods inherited from Connection

#<<, #closed?, #goaway, #new_stream, #ping, #receive, #settings, #window_update

Methods included from Emitter

#add_listener, #emit, #once

Methods included from FlowBuffer

#buffered_amount

Constructor Details

#initialize(**settings) ⇒ Server

Initialize new HTTP 2.0 server object.



24
25
26
27
28
29
30
31
32
# File 'lib/http/2/server.rb', line 24

def initialize(**settings)
  @stream_id    = 2
  @state        = :waiting_magic

  @local_role   = :server
  @remote_role  = :client

  super
end

Instance Method Details

#upgrade(settings, headers, body) ⇒ Object

GET / HTTP/1.1

Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

Requests that contain a payload body MUST be sent in their entirety before the client can send HTTP/2 frames. This means that a large request can block the use of the connection until it is completely sent.

If concurrency of an initial request with subsequent requests is important, an OPTIONS request can be used to perform the upgrade to HTTP/2, at the cost of an additional round trip.

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...
  • The first HTTP/2 frame sent by the server MUST be a server connection preface (Section 3.5) consisting of a SETTINGS frame.

  • Upon receiving the 101 response, the client MUST send a connection preface (Section 3.5), which includes a SETTINGS frame.

The HTTP/1.1 request that is sent prior to upgrade is assigned a stream identifier of 1 (see Section 5.1.1) with default priority values (Section 5.3.5). Stream 1 is implicitly “half-closed” from the client toward the server (see Section 5.1), since the request is completed as an HTTP/1.1 request. After commencing the HTTP/2 connection, stream 1 is used for the response.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/http/2/server.rb', line 66

def upgrade(settings, headers, body)
  @h2c_upgrade = :start

  # Pretend that we've received the preface
  #  - puts us into :waiting_connection_preface state
  #  - emits a SETTINGS frame to the client
  receive(CONNECTION_PREFACE_MAGIC)

  # Process received HTTP2-Settings payload
  buf = HTTP2::Buffer.new Base64.urlsafe_decode64(settings.to_s)
  header = @framer.common_header(
    length: buf.bytesize,
    type: :settings,
    stream: 0,
    flags: [],
  )
  buf.prepend(header)
  receive(buf)

  # Activate stream (id: 1) with on HTTP/1.1 request parameters
  stream = activate_stream(id: 1)
  emit(:stream, stream)

  headers_frame = {
    type:       :headers,
    stream:     1,
    weight:     DEFAULT_WEIGHT,
    dependency: 0,
    exclusive:  false,
    payload: headers,
  }

  if body.empty?
    headers_frame.merge!(flags: [:end_stream])
    stream << headers_frame
  else
    stream << headers_frame
    stream << { type: :data, stream: 1, payload: body, flags: [:end_stream] }
  end

  # Mark h2c upgrade as finished
  @h2c_upgrade = :finished

  # Transition back to :waiting_magic and wait for client's preface
  @state = :waiting_magic
end