Class: HTTPX::Connection::HTTP1
Constant Summary
collapse
- CRLF =
"\r\n"
Constants included
from Loggable
Loggable::COLORS
Instance Method Summary
collapse
Methods included from Loggable
#log, #log_exception
#emit, #on, #once
Constructor Details
#initialize(buffer, options) ⇒ HTTP1
Returns a new instance of HTTP1.
12
13
14
15
16
17
18
19
20
21
|
# File 'lib/httpx/connection/http1.rb', line 12
def initialize(buffer, options)
@options = Options.new(options)
@max_concurrent_requests = @options.max_concurrent_requests
@max_requests = Float::INFINITY
@parser = Parser::HTTP1.new(self)
@buffer = buffer
@version = [1, 1]
@pending = []
@requests = []
end
|
Instance Method Details
#<<(data) ⇒ Object
38
39
40
|
# File 'lib/httpx/connection/http1.rb', line 38
def <<(data)
@parser << data
end
|
#close ⇒ Object
27
28
29
30
|
# File 'lib/httpx/connection/http1.rb', line 27
def close
reset
emit(:close)
end
|
#consume ⇒ Object
63
64
65
66
67
|
# File 'lib/httpx/connection/http1.rb', line 63
def consume
@requests.each do |request|
handle(request)
end
end
|
#dispatch ⇒ Object
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# File 'lib/httpx/connection/http1.rb', line 121
def dispatch
if @request.expects?
reset
return handle(@request)
end
request = @request
@request = nil
@requests.shift
response = request.response
emit(:response, request, response)
if @parser.upgrade?
response << @parser.upgrade_data
throw(:called)
end
reset
@max_requests -= 1
send(@pending.shift) unless @pending.empty?
manage_connection(response)
end
|
#empty? ⇒ Boolean
32
33
34
35
36
|
# File 'lib/httpx/connection/http1.rb', line 32
def empty?
@requests.empty? || @requests.all? { |request| !request.response.nil? }
end
|
#handle_error(ex) ⇒ Object
144
145
146
147
148
149
150
151
152
|
# File 'lib/httpx/connection/http1.rb', line 144
def handle_error(ex)
if @pipelining
disable
else
@requests.each do |request|
emit(:error, request, ex)
end
end
end
|
#on_complete ⇒ Object
114
115
116
117
118
119
|
# File 'lib/httpx/connection/http1.rb', line 114
def on_complete
return unless @request
log(level: 2) { "parsing complete" }
dispatch
end
|
#on_data(chunk) ⇒ Object
104
105
106
107
108
109
110
111
112
|
# File 'lib/httpx/connection/http1.rb', line 104
def on_data(chunk)
return unless @request
log(color: :green) { "-> DATA: #{chunk.bytesize} bytes..." }
log(level: 2, color: :green) { "-> #{chunk.inspect}" }
response = @request.response
response << chunk
end
|
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/httpx/connection/http1.rb', line 77
def (h)
@request = @requests.first
return if @request.response
log(level: 2) { "headers received" }
= @request.options..new(h)
response = @request.options.response_class.new(@request,
@parser.status_code,
@parser.http_version.join("."),
)
log(color: :yellow) { "-> HEADLINE: #{response.status} HTTP/#{@parser.http_version.join(".")}" }
log(color: :yellow) { response..each.map { |f, v| "-> HEADER: #{f}: #{v}" }.join("\n") }
@request.response = response
on_complete if response.complete?
end
|
#on_start ⇒ Object
HTTP Parser callbacks
must be public methods, or else they won’t be reachable
73
74
75
|
# File 'lib/httpx/connection/http1.rb', line 73
def on_start
log(level: 2) { "parsing begins" }
end
|
#on_trailers(h) ⇒ Object
94
95
96
97
98
99
100
101
102
|
# File 'lib/httpx/connection/http1.rb', line 94
def on_trailers(h)
return unless @request
response = @request.response
log(level: 2) { "trailer headers received" }
log(color: :yellow) { h.each.map { |f, v| "-> HEADER: #{f}: #{v}" }.join("\n") }
response.(h)
end
|
#reenqueue! ⇒ Object
55
56
57
58
59
60
61
|
# File 'lib/httpx/connection/http1.rb', line 55
def reenqueue!
requests = @requests.dup
@requests.clear
requests.each do |request|
send(request)
end
end
|
#reset ⇒ Object
23
24
25
|
# File 'lib/httpx/connection/http1.rb', line 23
def reset
@parser.reset!
end
|
#send(request) ⇒ Object
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/httpx/connection/http1.rb', line 42
def send(request)
if @max_requests.positive? &&
@requests.size >= @max_concurrent_requests
@pending << request
return
end
unless @requests.include?(request)
@requests << request
@pipelining = true if @requests.size > 1
end
handle(request)
end
|