/
multipart.rb
59 lines (47 loc) · 1.39 KB
/
multipart.rb
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
# frozen_string_literal: true
require "securerandom"
require "http/form_data/multipart/param"
require "http/form_data/readable"
require "http/form_data/composite_io"
module HTTP
module FormData
# `multipart/form-data` form data.
class Multipart
include Readable
attr_reader :boundary
# @param [#to_h, Hash] data form data key-value Hash
def initialize(data, boundary: self.class.generate_boundary)
parts = Param.coerce FormData.ensure_hash data
@boundary = boundary.to_s.freeze
@io = CompositeIO.new [*parts.flat_map { |part| [glue, part] }, tail]
end
# Generates a string suitable for using as a boundary in multipart form
# data.
#
# @return [String]
def self.generate_boundary
("-" * 21) << SecureRandom.hex(21)
end
# Returns MIME type to be used for HTTP request `Content-Type` header.
#
# @return [String]
def content_type
"multipart/form-data; boundary=#{@boundary}"
end
# Returns form data content size to be used for HTTP request
# `Content-Length` header.
#
# @return [Integer]
alias content_length size
private
# @return [String]
def glue
@glue ||= "--#{@boundary}#{CRLF}"
end
# @return [String]
def tail
@tail ||= "--#{@boundary}--#{CRLF}"
end
end
end
end