Class: Async::HTTP::Protocol::HTTP1::Client
- Inherits:
-
Connection
- Object
- Protocol::HTTP1::Connection
- Connection
- Async::HTTP::Protocol::HTTP1::Client
- Defined in:
- lib/async/http/protocol/http1/client.rb
Overview
An HTTP/1 client connection that sends requests and reads responses.
Instance Attribute Summary collapse
-
#pool ⇒ Object
Returns the value of attribute pool.
Attributes inherited from Connection
Instance Method Summary collapse
-
#call(request, task: Task.current) ⇒ Object
Used by the client to send requests to the remote server.
-
#closed(error = nil) ⇒ Object
Called when the connection is closed, releasing it back to the pool.
-
#initialize ⇒ Client
constructor
Initialize the HTTP/1 client connection.
Methods inherited from Connection
#as_json, #concurrency, #http1?, #http2?, #peer, #reusable?, #to_json, #to_s, #viable?
Constructor Details
#initialize ⇒ Client
Initialize the HTTP/1 client connection.
15 16 17 18 19 |
# File 'lib/async/http/protocol/http1/client.rb', line 15 def initialize(...) super @pool = nil end |
Instance Attribute Details
#pool ⇒ Object
Returns the value of attribute pool.
21 22 23 |
# File 'lib/async/http/protocol/http1/client.rb', line 21 def pool @pool end |
Instance Method Details
#call(request, task: Task.current) ⇒ Object
Used by the client to send requests to the remote server.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/async/http/protocol/http1/client.rb', line 35 def call(request, task: Task.current) # Mark the start of the trailers: trailer = request.headers.trailer! headers = request.headers.header # We carefully interpret https://tools.ietf.org/html/rfc7230#section-6.3.1 to implement this correctly. target = request.path = request. # If we are using a CONNECT request, we need to use the authority as the target: if request.connect? target = = nil end write_request(, request.method, target, @version, headers) if request.body? body = request.body if protocol = request.protocol # This is a very tricky apect of handling HTTP/1 upgrade connections. In theory, this approach is a bit inefficient, because we spin up a task just to handle writing to the underlying stream when we could be writing to the stream directly. But we need to maintain some level of compatibility with HTTP/2. Additionally, we don't know if the upgrade request will be accepted, so starting to write the body at this point needs to be handled with care. task.async(annotation: "Upgrading request...") do # If this fails, this connection will be closed. write_upgrade_body(protocol, body) rescue => error self.close(error) end elsif request.connect? task.async(annotation: "Tunnneling request...") do write_tunnel_body(@version, body) rescue => error self.close(error) end else task.async(annotation: "Streaming request...") do # Once we start writing the body, we can't recover if the request fails. That's because the body might be generated dynamically, streaming, etc. write_body(@version, body, false, trailer) rescue => error self.close(error) end end elsif protocol = request.protocol write_upgrade_body(protocol) else write_body(@version, request.body, false, trailer) end return Response.read(self, request) rescue => error self.close(error) raise end |
#closed(error = nil) ⇒ Object
Called when the connection is closed, releasing it back to the pool.
24 25 26 27 28 29 30 31 32 |
# File 'lib/async/http/protocol/http1/client.rb', line 24 def closed(error = nil) super if pool = @pool @pool = nil # If the connection is not reusable, this will retire it from the connection pool and invoke `#close`. pool.release(self) end end |