Class: Protocol::Multipart::FormData

Inherits:
Mixed
  • Object
show all
Includes:
Escape
Defined in:
lib/protocol/multipart/form_data.rb

Overview

FormData class for handling multipart/form-data format used in HTTP forms. Extends Mixed to provide specific support for form fields with names and values.

Defined Under Namespace

Classes: Upload

Constant Summary collapse

MAXIMUM_FIELD_SIZE =

The default maximum size of a buffered form field.

2 * 1024 * 1024
MAXIMUM_UPLOAD_SIZE =

The default maximum size of a streamed file upload.

128 * 1024 * 1024
MAXIMUM_TOTAL_SIZE =

The default maximum combined size of all form fields and file uploads.

256 * 1024 * 1024

Instance Attribute Summary

Attributes inherited from Mixed

#The boundary string used to separate parts., #The parts of the body., #boundary, #parts

Attributes inherited from Part

#headers

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Escape

#escape_field_name, #unescape_field_name

Methods inherited from Mixed

#call, #initialize

Methods inherited from Part

#The headers as name/value pairs.=, #call, #initialize

Constructor Details

This class inherits a constructor from Protocol::Multipart::Mixed

Class Method Details

.mime_typeObject

Returns the MIME type for form data.



128
129
130
# File 'lib/protocol/multipart/form_data.rb', line 128

def self.mime_type
	"multipart/form-data"
end

.parse(readable, boundary, maximum_field_size: MAXIMUM_FIELD_SIZE, maximum_upload_size: MAXIMUM_UPLOAD_SIZE, maximum_total_size: MAXIMUM_TOTAL_SIZE, **options) ⇒ Object

Parse multipart form data.

Fields are yielded as strings. File uploads are yielded as streaming Upload instances and are only readable during the corresponding block invocation.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/protocol/multipart/form_data.rb', line 91

def self.parse(readable, boundary, maximum_field_size: MAXIMUM_FIELD_SIZE, maximum_upload_size: MAXIMUM_UPLOAD_SIZE, maximum_total_size: MAXIMUM_TOTAL_SIZE, **options)
	unless block_given?
		return enum_for(__method__, readable, boundary, maximum_field_size: maximum_field_size, maximum_upload_size: maximum_upload_size, maximum_total_size: maximum_total_size, **options)
	end
	
	total_limit = ByteLimit.new(maximum_total_size, name: :total_size)
	parser = 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, maximum_upload_size, total_limit)
			yield name, upload
			upload.discard
		else
			field_limit = ByteLimit.new(maximum_field_size, name: :field_size)
			value = String.new.b
			
			part.each do |chunk|
				field_limit.consume(chunk.bytesize)
				total_limit.consume(chunk.bytesize)
				value << chunk
			end
			
			yield name, value
		end
	end
end

Instance Method Details

#add_field(name, value, headers = {}) ⇒ Object

Adds a form field to the multipart form data.



138
139
140
141
142
143
144
145
146
# File 'lib/protocol/multipart/form_data.rb', line 138

def add_field(name, value, headers = {})
	headers = headers.merge(
		"content-disposition" => "form-data; name=\"#{escape_field_name name}\""
	)
	
	StringPart.new(headers, value).tap do |part|
		@parts << part
	end
end