lib/rack/rewindable_input.rb in rack-2.2.10 vs lib/rack/rewindable_input.rb in rack-3.0.0.beta1
- old
+ new
@@ -1,21 +1,33 @@
# -*- encoding: binary -*-
# frozen_string_literal: true
require 'tempfile'
+require_relative 'constants'
+
module Rack
# 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.
class RewindableInput
+ # Makes rack.input rewindable, for compatibility with applications and middleware
+ # designed for earlier versions of Rack (where rack.input was required to be
+ # rewindable).
+ class Middleware
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env[RACK_INPUT] = RewindableInput.new(env[RACK_INPUT])
+ @app.call(env)
+ end
+ end
+
def initialize(io)
@io = io
@rewindable_io = nil
@unlinked = false
end
@@ -38,10 +50,15 @@
def rewind
make_rewindable unless @rewindable_io
@rewindable_io.rewind
end
+ def size
+ make_rewindable unless @rewindable_io
+ @rewindable_io.size
+ end
+
# 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.
@@ -64,15 +81,17 @@
# 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.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