Class: HTTPX::Transcoder::Multipart::Encoder

Inherits:
Object
  • Object
show all
Defined in:
lib/httpx/transcoder/multipart/encoder.rb,
sig/transcoder/multipart.rbs

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(form) ⇒ Encoder

Returns a new instance of Encoder.

Parameters:

  • multipart_data (multipart_input)


8
9
10
11
12
13
14
15
16
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 8

def initialize(form)
  @boundary = ("-" * 21) << SecureRandom.hex(21)
  @part_index = 0
  @buffer = "".b

  @form = form
  @bytesize = 0
  @parts = to_parts(form)
end

Instance Attribute Details

#bytesizeInteger (readonly)

Returns the value of attribute bytesize.

Returns:

  • (Integer)


6
7
8
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 6

def bytesize
  @bytesize
end

Instance Method Details

#content_typeString

Returns:

  • (String)


18
19
20
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 18

def content_type
  "multipart/form-data; boundary=#{@boundary}"
end

#header_part(key, content_type, filename) ⇒ StringIO

Parameters:

  • key (String)
  • content_type (String)
  • filename (String, nil)

Returns:

  • (StringIO)


80
81
82
83
84
85
86
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 80

def header_part(key, content_type, filename)
  header = "--#{@boundary}\r\n".b
  header << "Content-Disposition: form-data; name=#{key.inspect}".b
  header << "; filename=#{filename.inspect}" if filename
  header << "\r\nContent-Type: #{content_type}\r\n\r\n"
  StringIO.new(header)
end

#read(length = nil, outbuf = nil) ⇒ String?

Parameters:

  • length (int, nil) (defaults to: nil)
  • buffer (string, nil)

Returns:

  • (String, nil)


28
29
30
31
32
33
34
35
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 28

def read(length = nil, outbuf = nil)
  data   = String(outbuf).clear.force_encoding(Encoding::BINARY) if outbuf
  data ||= "".b

  read_chunks(data, length)

  data unless length && data.empty?
end

#read_chunks(buffer, length = nil) ⇒ void

This method returns an undefined value.

Parameters:

  • buffer (String)
  • length (Integer, nil) (defaults to: nil)


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 88

def read_chunks(buffer, length = nil)
  while @part_index < @parts.size
    chunk = read_from_part(length)

    next unless chunk

    buffer << chunk.force_encoding(Encoding::BINARY)

    next unless length

    length -= chunk.bytesize

    break if length.zero?
  end
end

#read_from_part(max_length = nil) ⇒ String?

if there's a current part to read from, tries to read a chunk.

Parameters:

  • max_length (Integer, nil) (defaults to: nil)

Returns:

  • (String, nil)


105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 105

def read_from_part(max_length = nil)
  part = @parts[@part_index]

  chunk = part.read(max_length, @buffer)

  return chunk if chunk && !chunk.empty?

  part.close if part.respond_to?(:close)

  @part_index += 1

  nil
end

#rewindvoid

This method returns an undefined value.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 37

def rewind
  form = @form.each_with_object([]) do |(key, val), aux|
    if val.respond_to?(:path) && val.respond_to?(:reopen) && val.respond_to?(:closed?) && val.closed?
      # @type var val: File
      val = val.reopen(val.path, File::RDONLY)
    end
    val.rewind if val.respond_to?(:rewind)
    aux << [key, val]
  end
  @form = form
  @bytesize = 0
  @parts = to_parts(form)
  @part_index = 0
end

#to_parts(form) ⇒ Array[_Reader]

Parameters:

  • multipart_data (multipart_input)

Returns:

  • (Array[_Reader])


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
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 54

def to_parts(form)
  params = form.each_with_object([]) do |(key, val), aux|
    Transcoder::Multipart.normalize_keys(key, val) do |k, v|
      next if v.nil?

      value, content_type, filename = Part.call(v)

      header = header_part(k, content_type, filename)
      @bytesize += header.size
      aux << header

      @bytesize += value.size
      aux << value

      delimiter = StringIO.new("\r\n")
      @bytesize += delimiter.size
      aux << delimiter
    end
  end
  final_delimiter = StringIO.new("--#{@boundary}--\r\n")
  @bytesize += final_delimiter.size
  params << final_delimiter

  params
end

#to_sString

Returns:

  • (String)


22
23
24
25
26
# File 'lib/httpx/transcoder/multipart/encoder.rb', line 22

def to_s
  read || ""
ensure
  rewind
end