Class: PhusionPassenger::Utils::TeeInput

Inherits:
Object
  • Object
show all
Defined in:
lib/phusion_passenger/utils/tee_input.rb

Overview

acts like tee(1) on an input input to provide a input-like stream while providing rewindable semantics through a File/StringIO backing store. On the first pass, the input is only read on demand so your Rack application can use input notification (upload progress and like). This should fully conform to the Rack::Lint::InputWrapper specification on the public API. This class is intended to be a strict interpretation of Rack::Lint::InputWrapper functionality and will not support any deviations from it.

When processing uploads, Unicorn exposes a TeeInput object under “rack.input” of the Rack environment.

Constant Summary collapse

CONTENT_LENGTH =
"CONTENT_LENGTH".freeze
@@client_body_buffer_size =

The maximum size (in bytes) to buffer in memory before resorting to a temporary file. Default is 112 kilobytes.

112 * 1024

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(socket, env) ⇒ TeeInput

Initializes a new TeeInput object. You normally do not have to call this unless you are writing an HTTP server.



94
95
96
97
98
99
100
# File 'lib/phusion_passenger/utils/tee_input.rb', line 94

def initialize(socket, env)
  @len = env[CONTENT_LENGTH]
  @len = @len.to_i if @len
  @socket = socket
  @tmp = @len && @len <= @@client_body_buffer_size ?
         StringIO.new("") : TmpIO.new("PassengerTeeInput")
end

Class Method Details

.client_body_buffer_sizeObject

returns the maximum size of request bodies to buffer in memory, amounts larger than this are buffered to the filesystem



88
89
90
# File 'lib/phusion_passenger/utils/tee_input.rb', line 88

def self.client_body_buffer_size
  @@client_body_buffer_size
end

.client_body_buffer_size=(bytes) ⇒ Object

sets the maximum size of request bodies to buffer in memory, amounts larger than this are buffered to the filesystem



82
83
84
# File 'lib/phusion_passenger/utils/tee_input.rb', line 82

def self.client_body_buffer_size=(bytes)
  @@client_body_buffer_size = bytes
end

Instance Method Details

#closeObject



102
103
104
# File 'lib/phusion_passenger/utils/tee_input.rb', line 102

def close
  @tmp.close
end

#eachObject



136
137
138
139
140
141
142
# File 'lib/phusion_passenger/utils/tee_input.rb', line 136

def each
  while line = gets
    yield line
  end

  self # Rack does not specify what the return value is here
end

#getsObject



122
123
124
125
126
127
128
# File 'lib/phusion_passenger/utils/tee_input.rb', line 122

def gets
  if socket_drained?
    @tmp.gets
  else
    tee(@socket.gets)
  end
end

#read(*args) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/phusion_passenger/utils/tee_input.rb', line 114

def read(*args)
  if socket_drained?
    @tmp.read(*args)
  else
    tee(@socket.read(*args))
  end
end

#rewindObject



130
131
132
133
134
# File 'lib/phusion_passenger/utils/tee_input.rb', line 130

def rewind
  return 0 if 0 == @tmp.size
  consume! if !socket_drained?
  @tmp.rewind # Rack does not specify what the return value is here
end

#sizeObject



106
107
108
109
110
111
112
# File 'lib/phusion_passenger/utils/tee_input.rb', line 106

def size
  @len and return @len
  pos = @tmp.pos
  consume!
  @tmp.pos = pos
  @len = @tmp.size
end