# class Rack::RewindableInput

Class which can make any IO object rewindable, including non-rewindable ones. It does this by buffering the data into a tempfile, which is rewindable.

rack.input is required to be rewindable, so if your input stream IO is non-rewindable by nature (e.g. a pipe or a socket) then you can wrap it in an object of this class to easily make it rewindable.

Don't forget to call `close` when you're done. This frees up temporary resources that `RewindableInput` uses, though it does not close the original IO object.

### Public Class Methods

new(io) click to toggle source

    # File lib/rack/rewindable_input.rb, line 16
    def initialize(io)
      @io = io
      @rewindable_io = nil
      @unlinked = false
    end

### Public Instance Methods

close() click to toggle source

Closes this `RewindableInput` object without closing the originally wrapped IO object. Cleans up any temporary resources that this `RewindableInput` has created.

This method may be called multiple times. It does nothing on subsequent calls.

    # File lib/rack/rewindable_input.rb, line 47
    def close
      if @rewindable_io
        if @unlinked
          @rewindable_io.close
        else
          @rewindable_io.close!
        end
        @rewindable_io = nil
      end
    end

each(&block) click to toggle source

    # File lib/rack/rewindable_input.rb, line 32
    def each(&block)
      make_rewindable unless @rewindable_io
      @rewindable_io.each(&block)
    end

gets() click to toggle source

    # File lib/rack/rewindable_input.rb, line 22
    def gets
      make_rewindable unless @rewindable_io
      @rewindable_io.gets
    end

read(*args) click to toggle source

    # File lib/rack/rewindable_input.rb, line 27
    def read(*args)
      make_rewindable unless @rewindable_io
      @rewindable_io.read(*args)
    end

rewind() click to toggle source

    # File lib/rack/rewindable_input.rb, line 37
    def rewind
      make_rewindable unless @rewindable_io
      @rewindable_io.rewind
    end

### Private Instance Methods

filesystem_has_posix_semantics?() click to toggle source

    # File lib/rack/rewindable_input.rb, line 89
    def filesystem_has_posix_semantics?
      RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/
    end

make_rewindable() click to toggle source

    # File lib/rack/rewindable_input.rb, line 60
    def make_rewindable
      # Buffer all data into a tempfile. Since this tempfile is private to this
      # RewindableInput object, we chmod it so that nobody else can read or write
      # it. On POSIX filesystems we also unlink the file so that it doesn't
      # even have a file entry on the filesystem anymore, though we can still
      # access it because we have the file handle open.
      @rewindable_io = Tempfile.new('RackRewindableInput')
      @rewindable_io.chmod(0000)
      @rewindable_io.set_encoding(Encoding::BINARY) if @rewindable_io.respond_to?(:set_encoding)
      @rewindable_io.binmode
      if filesystem_has_posix_semantics?
        raise 'Unlink failed. IO closed.' if @rewindable_io.closed?
        @unlinked = true
      end

      buffer = "".dup
      while @io.read(1024 * 4, buffer)
        entire_buffer_written_out = false
        while !entire_buffer_written_out
          written = @rewindable_io.write(buffer)
          entire_buffer_written_out = written == buffer.bytesize
          if !entire_buffer_written_out
            buffer.slice!(0 .. written - 1)
          end
        end
      end
      @rewindable_io.rewind
    end