Sha256: d1e0d06f84d76a6c3d080d1557701ace6c58fd32d47ba67f4538900aab2200c4

Contents?: true

Size: 1.7 KB

Versions: 2

Compression:

Stored size: 1.7 KB

Contents

# encoding: utf-8

module HTTPkit
  # Streaming HTTP message serializer.
  #
  # @api public
  #
  class Serializer
    REQUEST_LINE = "%s %s HTTP/%.1f\r\n".freeze
    RESPONSE_LINE = "HTTP/%.1f %d %s\r\n".freeze
    HEADER = "%s: %s\r\n".freeze
    TRANSFER_ENCODING = 'Transfer-Encoding'.freeze
    CHUNKED = 'chunked'.freeze
    CONTENT_LENGTH = 'Content-Length'.freeze
    CRLF = "\r\n".freeze

    def initialize(message, writer)
      @message, @writer = message, writer
    end

    def serialize
      write(first_line)
      write(header_block)
      write_body
    end

    private

    def write(*data)
      @writer.call(data.join)
    end

    def first_line
      if Request === @message
        request_line
      else
        response_line
      end
    end

    def request_line
      sprintf(REQUEST_LINE,
              @message.http_method.upcase, @message.uri, @message.http_version)
    end

    def response_line
      sprintf(RESPONSE_LINE,
              @message.http_version, @message.status, @message.status_name)
    end

    def header_block
      @message.headers
        .reduce('') { |a, e| a << header_line(*e) } + CRLF
    end

    def header_line(key, value)
      if value.to_s.empty?
        ''
      else
        sprintf(HEADER, key,
                value.respond_to?(:join) ? value.join(', ') : value)
      end
    end

    def write_body
      body = @message.body
      if !body.length_known?
        body.each { |chunk| write_chunk(chunk) }
        write_chunk!('')
      else
        write(body)
      end
    end

    def write_chunk(chunk)
      write_chunk!(chunk) unless chunk.empty?
    end

    def write_chunk!(chunk)
      write(chunk.bytesize.to_s(16), CRLF, chunk, CRLF)
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
httpkit-0.6.0 lib/httpkit/serializer.rb
httpkit-0.6.0.pre.5 lib/httpkit/serializer.rb