class Parser
A configurable parser for multipart/form-data bodies.
Definitions
def initialize(field_size_limit: FIELD_SIZE_LIMIT, upload_size_limit: UPLOAD_SIZE_LIMIT, total_size_limit: TOTAL_SIZE_LIMIT, depth_limit: Protocol::URL::FormData::Nested::DEPTH_LIMIT, **options)
Initialize the form data parser.
Signature
-
parameter
field_size_limitInteger | Nil The buffered field size limit.
-
parameter
upload_size_limitInteger | Nil The file upload size limit.
-
parameter
total_size_limitInteger | Nil The combined size limit for all fields and uploads.
-
parameter
depth_limitInteger | Nil The bracketed form name depth limit.
-
parameter
optionsHash Limits passed to the underlying multipart parser.
Implementation
def initialize(field_size_limit: FIELD_SIZE_LIMIT, upload_size_limit: UPLOAD_SIZE_LIMIT, total_size_limit: TOTAL_SIZE_LIMIT, depth_limit: Protocol::URL::FormData::Nested::DEPTH_LIMIT, **options)
if depth_limit and depth_limit < 0
raise ArgumentError, "Form data limits must be non-negative!"
end
@field_size_limit = field_size_limit
@upload_size_limit = upload_size_limit
@total_size_limit = total_size_limit
@depth_limit = depth_limit
@options = options
end
def parse(readable, result = make_result, boundary:)
Parse multipart form data into a nested hash.
When a block is given, each value is passed through the block before assignment. The value returned by the block is assigned to the result. Uploads require a block because they must be consumed before parsing advances to the next part.
Signature
-
parameter
readableIO, IO::Stream The readable stream containing multipart form data.
-
parameter
resultObject The result to populate. It must support
#addand#to_h.-
parameter
boundaryString The multipart boundary.
-
yields
{|name, value| ...} Each form entry before assignment.
-
returns
Hash The nested form data.
Implementation
def parse(readable, result = make_result, boundary:)
each(readable, boundary:) do |name, value|
if block_given?
value = yield(name, value)
elsif value.is_a?(Upload)
raise ArgumentError, "A block is required to consume file uploads!"
end
result.add(name, value)
end
return result.to_h
end
def each(readable, boundary:)
Incrementally enumerate multipart form data.
Fields are yielded as strings. File uploads are yielded as streaming class Protocol::Multipart::FormData::Upload instances and are only readable during the corresponding block invocation.
Signature
-
parameter
readableIO, IO::Stream The readable stream containing multipart form data.
-
parameter
boundaryString The multipart boundary.
-
yields
{|name, value| ...} Each form field name and its string or streaming upload value.
-
returns
Enumerator | Boolean An enumerator without a block, or true when complete.
Implementation
def each(readable, boundary:)
return to_enum(__method__, readable, boundary:) unless block_given?
total_size_limit = ByteLimit.new(@total_size_limit, name: :total_size)
parser = Multipart::Parser.new(readable, boundary, **@options)
parser.each do |part|
disposition = part.headers["content-disposition"]
unless disposition&.type == "form-data" and name = disposition["name"]
raise ArgumentError, "Multipart form part is missing a form-data name!"
end
if filename = disposition["filename"]
upload = Upload.new(part, filename, @upload_size_limit, total_size_limit)
yield name, upload
upload.discard
else
field_size_limit = ByteLimit.new(@field_size_limit, name: :field_size)
value = String.new.b
part.each do |chunk|
field_size_limit.consume(chunk.bytesize)
total_size_limit.consume(chunk.bytesize)
value << chunk
end
yield name, value
end
end
end