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

#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



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/restclient/payload.rb', line 176

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



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/restclient/payload.rb', line 119

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

  @stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
  @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



204
205
206
# File 'lib/restclient/payload.rb', line 204

def close
  @stream.close!
end

#create_file_field(s, k, v) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/restclient/payload.rb', line 156

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



149
150
151
152
153
154
# File 'lib/restclient/payload.rb', line 149

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



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

def handle_key key
  key
end

#headersObject



200
201
202
# File 'lib/restclient/payload.rb', line 200

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

#mime_for(path) ⇒ Object



171
172
173
174
# File 'lib/restclient/payload.rb', line 171

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