class Rack::RewindableInput
RewindableInput uses, though it does not close the original IO object.
Don’t forget to call #close when you’re done. This frees up temporary resources that
this by buffering the data into a tempfile, which is rewindable.
Class which can make any IO object rewindable, including non-rewindable ones. It does
def close
has created.
wrapped IO object. Cleans up any temporary resources that this RewindableInput
Closes this RewindableInput object without closing the originally
def close if @rewindable_io if @unlinked @rewindable_io.close else @rewindable_io.close! end @rewindable_io = nil end end
def each(&block)
def each(&block) make_rewindable unless @rewindable_io @rewindable_io.each(&block) end
def filesystem_has_posix_semantics?
def filesystem_has_posix_semantics? RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/ end
def gets
def gets make_rewindable unless @rewindable_io @rewindable_io.gets end
def initialize(io)
def initialize(io) @io = io @rewindable_io = nil @unlinked = false end
def make_rewindable
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) @rewindable_io.binmode # :nocov: if filesystem_has_posix_semantics? raise 'Unlink failed. IO closed.' if @rewindable_io.closed? @unlinked = true end # :nocov: 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
def read(*args)
def read(*args) make_rewindable unless @rewindable_io @rewindable_io.read(*args) end
def rewind
def rewind make_rewindable unless @rewindable_io @rewindable_io.rewind end
def size
def size make_rewindable unless @rewindable_io @rewindable_io.size end