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