lib/async/http/protocol/http11.rb in async-http-0.10.0 vs lib/async/http/protocol/http11.rb in async-http-0.12.0
- old
+ new
@@ -18,22 +18,18 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
require 'async/io/protocol/line'
-require_relative 'request'
-require_relative 'response'
-require_relative '../headers'
+require_relative '../request'
+require_relative '../response'
module Async
module HTTP
module Protocol
# Implements basic HTTP/1.1 request/response.
class HTTP11 < Async::IO::Protocol::Line
- CONTENT_LENGTH = Headers['Content-Length']
- TRANSFER_ENCODING = Headers['Transfer-Encoding']
-
CRLF = "\r\n".freeze
def initialize(stream)
super(stream, CRLF)
@@ -62,11 +58,11 @@
def version
VERSION
end
def keep_alive?(headers)
- headers[:connection] != CLOSE
+ headers['connection'] != CLOSE
end
# Server loop.
def receive_requests(task: Task.current)
while true
@@ -123,11 +119,11 @@
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
+ return headers.delete('host'), method, path, version, headers, body
end
def write_response(version, status, headers, body)
@stream.write("#{version} #{status}\r\n")
write_headers(headers)
@@ -144,15 +140,15 @@
headers.each do |name, value|
@stream.write("#{name}: #{value}\r\n")
end
end
- def read_headers(headers = Headers.new)
+ def read_headers(headers = {})
# Parsing headers:
each_line do |line|
if line =~ /^([a-zA-Z\-]+):\s*(.+?)\s*$/
- headers[$1] = $2
+ headers[$1.downcase] = $2
else
break
end
end
@@ -167,41 +163,67 @@
next if chunk.size == 0
@stream.write("#{chunk.bytesize.to_s(16).upcase}\r\n")
@stream.write(chunk)
@stream.write(CRLF)
+ @stream.flush
end
@stream.write("0\r\n\r\n")
else
buffer = String.new
body.each{|chunk| buffer << chunk}
- @stream.write("Content-Length: #{chunk.bytesize}\r\n\r\n")
- @stream.write(chunk)
+ @stream.write("Content-Length: #{buffer.bytesize}\r\n\r\n")
+ @stream.write(buffer)
end
end
- def read_body(headers)
- if headers[:transfer_encoding] == 'chunked'
- buffer = Async::IO::BinaryString.new
+ class ChunkedBody
+ def initialize(protocol)
+ @protocol = protocol
+ @closed = false
+ end
+
+ def closed?
+ @closed
+ end
+
+ def each
+ return if @closed
while true
- size = read_line.to_i(16)
+ size = @protocol.read_line.to_i(16)
if size == 0
- read_line
- break
+ @closed = true
+ @protocol.read_line
+
+ return
end
- buffer << @stream.read(size)
+ yield @protocol.stream.read(size)
- read_line # Consume the trailing CRLF
+ @protocol.read_line # Consume the trailing CRLF
end
+ end
+
+ def read
+ buffer = Async::IO::BinaryString.new
+ self.each do |chunk|
+ buffer << chunk
+ end
+
return buffer
- elsif content_length = headers[:content_length]
- return @stream.read(Integer(content_length))
+ end
+ end
+
+ def read_body(headers)
+ if headers['transfer-encoding'] == 'chunked'
+ return ChunkedBody.new(self)
+ elsif content_length = headers['content-length']
+ return FixedBody.new(Integer(content_length), @stream)
end
end
end
end
end