Class: Quicsilver::Protocol::ResponseEncoder

Inherits:
Object
  • Object
show all
Defined in:
lib/quicsilver/protocol/response_encoder.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(status, headers, body, encoder: Qpack::Encoder.new, head_request: false, trailers: nil) ⇒ ResponseEncoder

Returns a new instance of ResponseEncoder.



20
21
22
23
24
25
26
27
# File 'lib/quicsilver/protocol/response_encoder.rb', line 20

def initialize(status, headers, body, encoder: Qpack::Encoder.new, head_request: false, trailers: nil)
  @status = status
  @headers = headers
  @body = body
  @encoder = encoder
  @head_request = head_request
  @trailers = trailers
end

Class Method Details

.encode_informational(status, headers, encoder: Qpack::Encoder.new) ⇒ Object

Encode an informational (1xx) response as a single HEADERS frame. RFC 9114 §4.1: informational responses are encoded as HEADERS with no body.

Raises:

  • (ArgumentError)


8
9
10
11
12
13
14
15
16
17
18
# File 'lib/quicsilver/protocol/response_encoder.rb', line 8

def self.encode_informational(status, headers, encoder: Qpack::Encoder.new)
  raise ArgumentError, "Informational status must be 1xx, got #{status}" unless (100..199).include?(status)

  pairs = [[":status", status.to_s]]
  headers.each { |name, value| pairs << [name.to_s.downcase, value.to_s] }
  encoded = encoder.encode(pairs)

  Protocol.encode_varint(FRAME_HEADERS) +
    Protocol.encode_varint(encoded.bytesize) +
    encoded
end

Instance Method Details

#encodeObject

Buffered encode - returns all frames at once



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/quicsilver/protocol/response_encoder.rb', line 30

def encode
  frames = "".b
  frames << build_frame(FRAME_HEADERS, @encoder.encode(all_headers))
  unless @head_request
    @body.each do |chunk|
      frames << build_frame(FRAME_DATA, chunk) unless chunk.empty?
    end
  end
  frames << build_frame(FRAME_HEADERS, @encoder.encode(trailer_headers)) if @trailers&.any?
  @body.close if @body.respond_to?(:close)
  frames
end

#stream_encode {|build_frame(FRAME_HEADERS, @encoder.encode(all_headers)), false| ... } ⇒ Object

Streaming encode - yields frames as they’re ready

Yields:



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/quicsilver/protocol/response_encoder.rb', line 44

def stream_encode
  yield build_frame(FRAME_HEADERS, @encoder.encode(all_headers)), false

  unless @head_request
    last_chunk = nil
    @body.each do |chunk|
      yield build_frame(FRAME_DATA, last_chunk), false if last_chunk && !last_chunk.empty?
      last_chunk = chunk
    end

    if @trailers&.any?
      yield build_frame(FRAME_DATA, last_chunk), false if last_chunk && !last_chunk.empty?
      yield build_frame(FRAME_HEADERS, @encoder.encode(trailer_headers)), true
    elsif last_chunk && !last_chunk.empty?
      yield build_frame(FRAME_DATA, last_chunk), true
    else
      yield "".b, true
    end
  else
    yield "".b, true
  end

  @body.close if @body.respond_to?(:close)
end