class HTTPX::Connection::HTTP1

  1. lib/httpx/connection/http1.rb
Superclass: Object

Included modules

  1. Callbacks
  2. Loggable

Constants

CRLF = "\r\n"  
MAX_REQUESTS = 100  
UPCASED = { "www-authenticate" => "WWW-Authenticate", "http2-settings" => "HTTP2-Settings", }.freeze  

Attributes

pending [R]

Public Class methods

new (buffer, options)
[show source]
   # File lib/httpx/connection/http1.rb
15 def initialize(buffer, options)
16   @options = Options.new(options)
17   @max_concurrent_requests = @options.max_concurrent_requests || MAX_REQUESTS
18   @max_requests = @options.max_requests || MAX_REQUESTS
19   @parser = Parser::HTTP1.new(self)
20   @buffer = buffer
21   @version = [1, 1]
22   @pending = []
23   @requests = []
24 end

Public Instance methods

<< (data)
[show source]
   # File lib/httpx/connection/http1.rb
46 def <<(data)
47   @parser << data
48 end
close ()
[show source]
   # File lib/httpx/connection/http1.rb
31 def close
32   reset
33   emit(:close)
34 end
consume ()
[show source]
   # File lib/httpx/connection/http1.rb
62 def consume
63   requests_limit = [@max_concurrent_requests, @max_requests, @requests.size].min
64   @requests.each_with_index do |request, idx|
65     break if idx >= requests_limit
66 
67     handle(request)
68   end
69 end
dispatch ()
[show source]
    # File lib/httpx/connection/http1.rb
123 def dispatch
124   if @request.expects?
125     @parser.reset!
126     return handle(@request)
127   end
128 
129   request = @request
130   @request = nil
131   @requests.shift
132   response = request.response
133   emit(:response, request, response)
134 
135   if @parser.upgrade?
136     response << @parser.upgrade_data
137     throw(:called)
138   end
139 
140   @parser.reset!
141   @max_requests -= 1
142   manage_connection(response)
143   send(@pending.shift) unless @pending.empty?
144 end
empty? ()
[show source]
   # File lib/httpx/connection/http1.rb
40 def empty?
41   # this means that for every request there's an available
42   # partial response, so there are no in-flight requests waiting.
43   @requests.empty? || @requests.all? { |request| !request.response.nil? }
44 end
exhausted? ()
[show source]
   # File lib/httpx/connection/http1.rb
36 def exhausted?
37   !@max_requests.positive?
38 end
handle_error (ex)
[show source]
    # File lib/httpx/connection/http1.rb
146 def handle_error(ex)
147   if @pipelining
148     disable
149   else
150     @requests.each do |request|
151       emit(:error, request, ex)
152     end
153   end
154 end
on_complete ()
[show source]
    # File lib/httpx/connection/http1.rb
116 def on_complete
117   return unless @request
118 
119   log(level: 2) { "parsing complete" }
120   dispatch
121 end
on_data (chunk)
[show source]
    # File lib/httpx/connection/http1.rb
106 def on_data(chunk)
107   return unless @request
108 
109   log(color: :green) { "-> DATA: #{chunk.bytesize} bytes..." }
110   log(level: 2, color: :green) { "-> #{chunk.inspect}" }
111   response = @request.response
112 
113   response << chunk
114 end
on_headers (h)
[show source]
   # File lib/httpx/connection/http1.rb
79 def on_headers(h)
80   @request = @requests.first
81   return if @request.response
82 
83   log(level: 2) { "headers received" }
84   headers = @request.options.headers_class.new(h)
85   response = @request.options.response_class.new(@request,
86                                                  @parser.status_code,
87                                                  @parser.http_version.join("."),
88                                                  headers)
89   log(color: :yellow) { "-> HEADLINE: #{response.status} HTTP/#{@parser.http_version.join(".")}" }
90   log(color: :yellow) { response.headers.each.map { |f, v| "-> HEADER: #{f}: #{v}" }.join("\n") }
91 
92   @request.response = response
93   on_complete if response.complete?
94 end
on_start ()

HTTP Parser callbacks

must be public methods, or else they won't be reachable

[show source]
   # File lib/httpx/connection/http1.rb
75 def on_start
76   log(level: 2) { "parsing begins" }
77 end
on_trailers (h)
[show source]
    # File lib/httpx/connection/http1.rb
 96 def on_trailers(h)
 97   return unless @request
 98 
 99   response = @request.response
100   log(level: 2) { "trailer headers received" }
101 
102   log(color: :yellow) { h.each.map { |f, v| "-> HEADER: #{f}: #{v}" }.join("\n") }
103   response.merge_headers(h)
104 end
reset ()
[show source]
   # File lib/httpx/connection/http1.rb
26 def reset
27   @max_requests = @options.max_requests || MAX_REQUESTS
28   @parser.reset!
29 end
send (request)
[show source]
   # File lib/httpx/connection/http1.rb
50 def send(request)
51   unless @max_requests.positive?
52     @pending << request
53     return
54   end
55 
56   return if @requests.include?(request)
57 
58   @requests << request
59   @pipelining = true if @requests.size > 1
60 end