Class: HTTP1Adapter

Inherits:
Object
  • Object
show all
Defined in:
lib/polyphony/http/client/http1.rb

Overview

HTTP 1 adapter

Constant Summary collapse

HTTP1_REQUEST =
<<~HTTP.gsub("\n", "\r\n")
  %<method>s %<request>s HTTP/1.1
  Host: %<host>s
  %<headers>s

HTTP

Instance Method Summary collapse

Constructor Details

#initialize(socket) ⇒ HTTP1Adapter

Returns a new instance of HTTP1Adapter.



11
12
13
14
# File 'lib/polyphony/http/client/http1.rb', line 11

def initialize(socket)
  @socket = socket
  @parser = HTTP::Parser.new(self)
end

Instance Method Details

#bodyObject



57
58
59
60
61
# File 'lib/polyphony/http/client/http1.rb', line 57

def body
  @waiting_for_chunk = nil
  consume_response
  @buffered_body
end

#consume_responseObject



95
96
97
98
99
100
101
# File 'lib/polyphony/http/client/http1.rb', line 95

def consume_response
  while !@done && (data = @socket.readpartial(8192))
    @parser << data
  end

  raise 'Socket closed by host' unless @done
end

#each_chunk(&block) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/polyphony/http/client/http1.rb', line 63

def each_chunk(&block)
  if (body = @buffered_body)
    @buffered_body = nil
    @waiting_for_chunk = true
    block.(body)
  end
  while !@done && (data = @socket.readpartial(8192))
    @parser << data
  end
  raise 'Socket closed by host' unless @done

  @buffered_chunks.each(&block)
end

#format_headers(headers) ⇒ Object



122
123
124
# File 'lib/polyphony/http/client/http1.rb', line 122

def format_headers(headers)
  headers.map { |k, v| "#{k}: #{v}\r\n" }.join
end

#format_http1_request(ctx) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/polyphony/http/client/http1.rb', line 110

def format_http1_request(ctx)
  headers = format_headers(ctx)

  format(
    HTTP1_REQUEST,
    method:  ctx[:method],
    request: ctx[:uri].request_uri,
    host:    ctx[:uri].host,
    headers: headers
  )
end

#next_body_chunkObject



77
78
79
80
81
82
83
84
# File 'lib/polyphony/http/client/http1.rb', line 77

def next_body_chunk
  return nil if @done
  if @buffered_chunks && !@buffered_chunks.empty?
    return @buffered_chunks.shift
  end

  read_next_body_chunk
end

#on_body(chunk) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/polyphony/http/client/http1.rb', line 20

def on_body(chunk)
  if @waiting_for_chunk
    @buffered_chunks ||= []
    @buffered_chunks << chunk
  elsif @buffered_body
    @buffered_body << chunk
  else
    @buffered_body = +chunk
  end
end

#on_headers_complete(headers) ⇒ Object



16
17
18
# File 'lib/polyphony/http/client/http1.rb', line 16

def on_headers_complete(headers)
  @headers = headers
end

#on_message_completeObject



31
32
33
# File 'lib/polyphony/http/client/http1.rb', line 31

def on_message_complete
  @done = true
end

#protocolObject



126
127
128
# File 'lib/polyphony/http/client/http1.rb', line 126

def protocol
  :http1
end

#read_headersObject



48
49
50
51
52
53
54
55
# File 'lib/polyphony/http/client/http1.rb', line 48

def read_headers
  @headers = nil
  while !@headers && (data = @socket.readpartial(8192))
    @parser << data
  end

  raise 'Socket closed by host' unless @headers
end

#read_next_body_chunkObject



86
87
88
89
90
91
92
93
# File 'lib/polyphony/http/client/http1.rb', line 86

def read_next_body_chunk
  @waiting_for_chunk = true
  while !@done && (data = @socket.readpartial(8192))
    @parser << data
    break unless @buffered_chunks.empty?
  end
  @buffered_chunks.shift
end

#request(ctx) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/polyphony/http/client/http1.rb', line 35

def request(ctx)
  # consume previous response if not finished
  consume_response if @done == false

  @socket << format_http1_request(ctx)

  @buffered_body = nil
  @done = false

  read_headers
  Response.new(self, @parser.status_code, @headers)
end