Class: Protocol::Multipart::Parser
- Inherits:
-
Object
- Object
- Protocol::Multipart::Parser
- Defined in:
- lib/protocol/multipart/parser.rb
Overview
A parser for multipart data based on RFC 2046 and RFC 2387. Parses multipart bodies and provides an enumerable interface to access the parts.
Defined Under Namespace
Classes: Part
Constant Summary collapse
- MAXIMUM_PREAMBLE_SIZE =
The default maximum number of preamble bytes before the first boundary.
64 * 1024
- MAXIMUM_HEADER_SIZE =
The default maximum number of header bytes in each part.
64 * 1024
- MAXIMUM_HEADER_COUNT =
The default maximum number of headers in each part.
64- MAXIMUM_PART_COUNT =
The default maximum number of parts.
128
Instance Method Summary collapse
-
#each ⇒ Object
Enumerate through each part in the multipart data.
-
#initialize(readable, boundary, maximum_preamble_size: MAXIMUM_PREAMBLE_SIZE, maximum_header_size: MAXIMUM_HEADER_SIZE, maximum_header_count: MAXIMUM_HEADER_COUNT, maximum_part_count: MAXIMUM_PART_COUNT) ⇒ Parser
constructor
Initialize a new multipart parser.
Constructor Details
#initialize(readable, boundary, maximum_preamble_size: MAXIMUM_PREAMBLE_SIZE, maximum_header_size: MAXIMUM_HEADER_SIZE, maximum_header_count: MAXIMUM_HEADER_COUNT, maximum_part_count: MAXIMUM_PART_COUNT) ⇒ Parser
Initialize a new multipart parser.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/protocol/multipart/parser.rb', line 170 def initialize(readable, boundary, maximum_preamble_size: MAXIMUM_PREAMBLE_SIZE, maximum_header_size: MAXIMUM_HEADER_SIZE, maximum_header_count: MAXIMUM_HEADER_COUNT, maximum_part_count: MAXIMUM_PART_COUNT) limits = [maximum_preamble_size, maximum_header_size, maximum_header_count, maximum_part_count] if limits.any?{|limit| limit and limit < 0} raise ArgumentError, "Multipart limits must be non-negative!" end @readable = IO::Stream(readable) @boundary = boundary @maximum_preamble_size = maximum_preamble_size @maximum_header_size = maximum_header_size @maximum_header_count = maximum_header_count @maximum_part_count = maximum_part_count @boundary_marker = "--#{@boundary}\r\n".freeze end |
Instance Method Details
#each ⇒ Object
Enumerate through each part in the multipart data. Yields each part for processing. If no block is given, returns an enumerator.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/protocol/multipart/parser.rb', line 191 def each return to_enum unless block_given? preamble_size = 0 # Read lines until we find the first boundary: while true if line = read_line(preamble_size, @maximum_preamble_size, allowance: @boundary_marker.bytesize, chomp: false) if line == @boundary_marker break else preamble_size += line.bytesize check_limit(:preamble_size, preamble_size, @maximum_preamble_size) end else # End of stream reached without finding boundary: raise EOFError, "No multipart boundary found in stream!" end end part_count = 0 while true part_count += 1 check_limit(:part_count, part_count, @maximum_part_count) part = read_part break unless part if part.read_empty_boundary? else yield part # Advance to the next boundary after the consumer returns normally. If the consumer raises, stop parsing without draining the request body. part.discard end # Check if this was the last part: break if part.closing_boundary? end return true end |