1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
module HTTP
module FormData
class Multipart
# Utility class to represent multi-part chunks
class Param
# @param [#to_s] name
# @param [FormData::File, #to_s] value
def initialize(name, value)
@name, @value = name.to_s, value
@header = "Content-Disposition: form-data; name=#{@name.inspect}"
return unless file?
@header << "; filename=#{value.filename.inspect}"
@header << CRLF
@header << "Content-Type: #{value.mime_type}"
end
# Returns body part with headers and data.
#
# @example With {FormData::File} value
#
# Content-Disposition: form-data; name="avatar"; filename="avatar.png"
# Content-Type: application/octet-stream
#
# ...data of avatar.png...
#
# @example With non-{FormData::File} value
#
# Content-Disposition: form-data; name="username"
#
# ixti
#
# @return [String]
def to_s
"#{@header}#{CRLF * 2}#{@value}"
end
# Calculates size of a part (headers + body).
#
# @return [Fixnum]
def size
size = @header.bytesize + (CRLF.bytesize * 2)
if file?
size + @value.size
else
size + @value.to_s.bytesize
end
end
# Flattens given `data` Hash into an array of `Param`'s.
# Nested array are unwinded.
# Behavior is similar to `URL.encode_www_form`.
#
# @param [Hash] data
# @return [Array<FormData::MultiPart::Param>]
def self.coerce(data)
params = []
data.each do |name, values|
Array(values).each do |value|
params << new(name, value)
end
end
params
end
private
# Tells whenever value is a {FormData::File} or not.
#
# @return [Boolean]
def file?
@value.is_a? FormData::File
end
end
end
end
end
|