Class: Async::HTTP::Protocol::HTTP11
- Inherits:
-
IO::Protocol::Line
- Object
- IO::Protocol::Line
- Async::HTTP::Protocol::HTTP11
- Defined in:
- lib/async/http/protocol/http11.rb
Overview
Implements basic HTTP/1.1 request/response.
Direct Known Subclasses
Constant Summary collapse
- CRLF =
"\r\n".freeze
- CLOSE =
'close'.freeze
- VERSION =
"HTTP/1.1".freeze
Instance Attribute Summary collapse
-
#count ⇒ Object
readonly
Returns the value of attribute count.
Instance Method Summary collapse
- #call(request) ⇒ Object
-
#initialize(stream) ⇒ HTTP11
constructor
A new instance of HTTP11.
-
#multiplex ⇒ Object
Only one simultaneous connection at a time.
- #persistent?(headers) ⇒ Boolean
- #read_request ⇒ Object
- #read_response ⇒ Object
-
#receive_requests(task: Task.current) ⇒ Object
Server loop.
- #reusable? ⇒ Boolean
- #version ⇒ Object
- #write_request(authority, method, path, version, headers, body) ⇒ Object
- #write_response(version, status, headers, body) ⇒ Object
Constructor Details
#initialize(stream) ⇒ HTTP11
Returns a new instance of HTTP11.
37 38 39 40 41 42 |
# File 'lib/async/http/protocol/http11.rb', line 37 def initialize(stream) super(stream, CRLF) @persistent = true @count = 0 end |
Instance Attribute Details
#count ⇒ Object (readonly)
Returns the value of attribute count.
44 45 46 |
# File 'lib/async/http/protocol/http11.rb', line 44 def count @count end |
Instance Method Details
#call(request) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/async/http/protocol/http11.rb', line 97 def call(request) @count += 1 request.version ||= self.version Async.logger.debug(self) {"#{request.method} #{request.path} #{request.headers.inspect}"} write_request(request., request.method, request.path, request.version, request.headers, request.body) return Response.new(*read_response) rescue EOFError Async.logger.debug(self) {"Connection failed with EOFError after #{@count} requests."} return nil end |
#multiplex ⇒ Object
Only one simultaneous connection at a time.
47 48 49 |
# File 'lib/async/http/protocol/http11.rb', line 47 def multiplex 1 end |
#persistent?(headers) ⇒ Boolean
68 69 70 |
# File 'lib/async/http/protocol/http11.rb', line 68 def persistent?(headers) headers['connection'] != CLOSE end |
#read_request ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/async/http/protocol/http11.rb', line 133 def read_request method, path, version = read_line.split(/\s+/, 3) headers = read_headers body = read_body(headers) return headers.delete('host'), method, path, version, headers, body end |
#read_response ⇒ Object
123 124 125 126 127 128 129 130 131 |
# File 'lib/async/http/protocol/http11.rb', line 123 def read_response version, status, reason = read_line.split(/\s+/, 3) headers = read_headers body = read_body(headers) @persistent = persistent?(headers) return version, Integer(status), reason, headers, body end |
#receive_requests(task: Task.current) ⇒ Object
Server loop.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/async/http/protocol/http11.rb', line 73 def receive_requests(task: Task.current) while true request = Request.new(*read_request) @count += 1 response = yield request response.version ||= request.version write_response(response.version, response.status, response.headers, response.body) request.finish unless persistent?(request.headers) and persistent?(response.headers) @persistent = false break end # This ensures we yield at least once every iteration of the loop and allow other fibers to execute. task.yield end end |
#reusable? ⇒ Boolean
51 52 53 |
# File 'lib/async/http/protocol/http11.rb', line 51 def reusable? @persistent end |
#version ⇒ Object
64 65 66 |
# File 'lib/async/http/protocol/http11.rb', line 64 def version VERSION end |
#write_request(authority, method, path, version, headers, body) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/async/http/protocol/http11.rb', line 111 def write_request(, method, path, version, headers, body) @stream.write("#{method} #{path} #{version}\r\n") @stream.write("Host: #{authority}\r\n") write_headers(headers) write_body(body) @stream.flush return true end |
#write_response(version, status, headers, body) ⇒ Object
141 142 143 144 145 146 147 148 149 |
# File 'lib/async/http/protocol/http11.rb', line 141 def write_response(version, status, headers, body) @stream.write("#{version} #{status}\r\n") write_headers(headers) write_body(body) @stream.flush return true end |