Class: RestClient::Payload::Multipart

Inherits:
Base
  • Object
show all
Defined in:
lib/restclient/payload.rb

Constant Summary collapse

EOL =
"\r\n"

Instance Method Summary collapse

Methods inherited from Base

#closed?, #initialize, #read, #short_inspect, #size, #to_s, #to_s_inspect

Constructor Details

This class inherits a constructor from RestClient::Payload::Base

Instance Method Details

#boundaryObject


201
202
203
204
205
206
207
208
209
210
211
# File 'lib/restclient/payload.rb', line 201

def boundary
  return @boundary if defined?(@boundary) && @boundary

  # Use the same algorithm used by WebKit: generate 16 random
  # alphanumeric characters, replacing `+` `/` with `A` `B` (included in
  # the list twice) to round out the set of 64.
  s = SecureRandom.base64(12)
  s.tr!('+/', 'AB')

  @boundary = '----RubyFormBoundary' + s
end

#build_stream(params) ⇒ Object


144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/restclient/payload.rb', line 144

def build_stream(params)
  b = '--' + boundary

  @stream = Tempfile.new('rest-client.multipart.')
  @stream.binmode
  @stream.write(b + EOL)

  case params
  when Hash, ParamsArray
    x = Utils.flatten_params(params)
  else
    x = params
  end

  last_index = x.length - 1
  x.each_with_index do |a, index|
    k, v = * a
    if v.respond_to?(:read) && v.respond_to?(:path)
      create_file_field(@stream, k, v)
    else
      create_regular_field(@stream, k, v)
    end
    @stream.write(EOL + b)
    @stream.write(EOL) unless last_index == index
  end
  @stream.write('--')
  @stream.write(EOL)
  @stream.seek(0)
end

#closeObject


229
230
231
# File 'lib/restclient/payload.rb', line 229

def close
  @stream.close!
end

#create_file_field(s, k, v) ⇒ Object


181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/restclient/payload.rb', line 181

def create_file_field(s, k, v)
  begin
    s.write("Content-Disposition: form-data;")
    s.write(" name=\"#{k}\";") unless (k.nil? || k=='')
    s.write(" filename=\"#{v.respond_to?(:original_filename) ? v.original_filename : File.basename(v.path)}\"#{EOL}")
    s.write("Content-Type: #{v.respond_to?(:content_type) ? v.content_type : mime_for(v.path)}#{EOL}")
    s.write(EOL)
    while (data = v.read(8124))
      s.write(data)
    end
  ensure
    v.close if v.respond_to?(:close)
  end
end

#create_regular_field(s, k, v) ⇒ Object


174
175
176
177
178
179
# File 'lib/restclient/payload.rb', line 174

def create_regular_field(s, k, v)
  s.write("Content-Disposition: form-data; name=\"#{k}\"")
  s.write(EOL)
  s.write(EOL)
  s.write(v)
end

#handle_key(key) ⇒ Object

for Multipart do not escape the keys

Ostensibly multipart keys MAY be percent encoded per RFC 7578, but in practice no major browser that I'm aware of uses percent encoding.

Further discussion of multipart encoding: github.com/rest-client/rest-client/pull/403#issuecomment-156976930


221
222
223
# File 'lib/restclient/payload.rb', line 221

def handle_key key
  key
end

#headersObject


225
226
227
# File 'lib/restclient/payload.rb', line 225

def headers
  super.merge({'Content-Type' => %Q{multipart/form-data; boundary=#{boundary}}})
end

#mime_for(path) ⇒ Object


196
197
198
199
# File 'lib/restclient/payload.rb', line 196

def mime_for(path)
  mime = MIME::Types.type_for path
  mime.empty? ? 'text/plain' : mime[0].content_type
end