Sha256: 95a3be6e82d983ef5348a7d9098a057fa45f970fd4418c1bcc0b040cff3e2cda

Contents?: true

Size: 1.97 KB

Versions: 6

Compression:

Stored size: 1.97 KB

Contents

# frozen_string_literal: true

module HTTP
  class Request
    class Body
      attr_reader :source

      def initialize(source)
        @source = source

        validate_source_type!
      end

      # Returns size which should be used for the "Content-Length" header.
      #
      # @return [Integer]
      def size
        if @source.is_a?(String)
          @source.bytesize
        elsif @source.respond_to?(:read)
          raise RequestError, "IO object must respond to #size" unless @source.respond_to?(:size)
          @source.size
        elsif @source.nil?
          0
        else
          raise RequestError, "cannot determine size of body: #{@source.inspect}"
        end
      end

      # Yields chunks of content to be streamed to the request body.
      #
      # @yieldparam [String]
      def each(&block)
        if @source.is_a?(String)
          yield @source
        elsif @source.respond_to?(:read)
          IO.copy_stream(@source, ProcIO.new(block))
          @source.rewind if @source.respond_to?(:rewind)
        elsif @source.is_a?(Enumerable)
          @source.each(&block)
        end
      end

      # Request bodies are equivalent when they have the same source.
      def ==(other)
        self.class == other.class && self.source == other.source # rubocop:disable Style/RedundantSelf
      end

      private

      def validate_source_type!
        return if @source.is_a?(String)
        return if @source.respond_to?(:read)
        return if @source.is_a?(Enumerable)
        return if @source.nil?

        raise RequestError, "body of wrong type: #{@source.class}"
      end

      # This class provides a "writable IO" wrapper around a proc object, with
      # #write simply calling the proc, which we can pass in as the
      # "destination IO" in IO.copy_stream.
      class ProcIO
        def initialize(block)
          @block = block
        end

        def write(data)
          @block.call(data)
          data.bytesize
        end
      end
    end
  end
end

Version data entries

6 entries across 6 versions & 1 rubygems

Version Path
http-4.0.4 lib/http/request/body.rb
http-5.0.0.pre lib/http/request/body.rb
http-4.0.3 lib/http/request/body.rb
http-4.0.2 lib/http/request/body.rb
http-4.0.1 lib/http/request/body.rb
http-4.0.0 lib/http/request/body.rb