Class: Rack::Multipart::Parser
- Inherits:
-
Object
- Object
- Rack::Multipart::Parser
- Defined in:
- lib/rack/multipart/parser.rb
Overview
Rack::Multipart::Parser handles parsing of multipart/form-data requests.
File Parameter Contents
When processing file uploads, the parser returns a hash containing information about uploaded files. For file
parameters, the hash includes:
-
:filename
- The original filename, already URL decoded by the parser -
:type
- The content type of the uploaded file -
:name
- The parameter name from the form -
:tempfile
- A Tempfile object containing the uploaded data -
:head
- The raw header content for this part
Defined Under Namespace
Classes: BoundedIO, Collector, MultipartInfo
Constant Summary collapse
- BUFSIZE =
1_048_576
- TEXT_PLAIN =
"text/plain"
- TEMPFILE_FACTORY =
lambda { |filename, content_type| extension = ::File.extname(filename.gsub("\0", '%00'))[0, 129] Tempfile.new(["RackMultipart", extension]) }
- EMPTY =
MultipartInfo.new(nil, [])
Instance Attribute Summary collapse
-
#state ⇒ Object
readonly
Returns the value of attribute state.
Class Method Summary collapse
- .parse(io, content_length, content_type, tmpfile, bufsize, qp) ⇒ Object
- .parse_boundary(content_type) ⇒ Object
Instance Method Summary collapse
-
#initialize(boundary, tempfile, bufsize, query_parser) ⇒ Parser
constructor
A new instance of Parser.
- #parse(io) ⇒ Object
- #result ⇒ Object
Constructor Details
#initialize(boundary, tempfile, bufsize, query_parser) ⇒ Parser
Returns a new instance of Parser.
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/rack/multipart/parser.rb', line 214 def initialize(boundary, tempfile, bufsize, query_parser) @query_parser = query_parser @params = query_parser.make_params @bufsize = bufsize @state = :FAST_FORWARD @mime_index = 0 @collector = Collector.new tempfile @sbuf = StringScanner.new("".dup) @body_regex = /(?:#{EOL}|\A)--#{Regexp.quote(boundary)}(?:#{EOL}|--)/m @body_regex_at_end = /#{@body_regex}\z/m @end_boundary_size = boundary.bytesize + 4 # (-- at start, -- at finish) @rx_max_size = boundary.bytesize + 6 # (\r\n-- at start, either \r\n or -- at finish) @head_regex = /(.*?#{EOL})#{EOL}/m end |
Instance Attribute Details
#state ⇒ Object (readonly)
Returns the value of attribute state.
212 213 214 |
# File 'lib/rack/multipart/parser.rb', line 212 def state @state end |
Class Method Details
.parse(io, content_length, content_type, tmpfile, bufsize, qp) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/rack/multipart/parser.rb', line 101 def self.parse(io, content_length, content_type, tmpfile, bufsize, qp) return EMPTY if 0 == content_length boundary = parse_boundary content_type return EMPTY unless boundary if boundary.length > 70 # RFC 1521 Section 7.2.1 imposes a 70 character maximum for the boundary. # Most clients use no more than 55 characters. raise BoundaryTooLongError, "multipart boundary size too large (#{boundary.length} characters)" end io = BoundedIO.new(io, content_length) if content_length parser = new(boundary, tmpfile, bufsize, qp) parser.parse(io) parser.result end |
.parse_boundary(content_type) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/rack/multipart/parser.rb', line 94 def self.parse_boundary(content_type) return unless content_type data = content_type.match(MULTIPART) return unless data data[1] end |
Instance Method Details
#parse(io) ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/rack/multipart/parser.rb', line 231 def parse(io) outbuf = String.new read_data(io, outbuf) loop do status = case @state when :FAST_FORWARD handle_fast_forward when :CONSUME_TOKEN handle_consume_token when :MIME_HEAD handle_mime_head when :MIME_BODY handle_mime_body else # when :DONE return end read_data(io, outbuf) if status == :want_read end end |
#result ⇒ Object
254 255 256 257 258 259 260 261 262 263 |
# File 'lib/rack/multipart/parser.rb', line 254 def result @collector.each do |part| part.get_data do |data| tag_multipart_encoding(part.filename, part.content_type, part.name, data) name, data = handle_dummy_encoding(part.name, data) @query_parser.normalize_params(@params, name, data) end end MultipartInfo.new @params.to_params_hash, @collector.find_all(&:file?).map(&:body) end |