Module: Jimmu::BodyParser
- Defined in:
- lib/jimmu.rb
Overview
Parses application/x-www-form-urlencoded and multipart/form-data request bodies, and application/json bodies. All parsing is done byte-safe (ASCII-8BIT) throughout and only the final text values are tagged back to UTF-8, so binary upload data is never at risk of being mangled or raising encoding errors partway through.
Class Method Summary collapse
- .extract_boundary(content_type) ⇒ Object
- .parse_json(raw_body) ⇒ Object
-
.parse_multipart(raw_body, boundary) ⇒ Object
Returns [fields_hash, files_hash], both keyed by Symbol.
- .parse_urlencoded(raw_body) ⇒ Object
Class Method Details
.extract_boundary(content_type) ⇒ Object
487 488 489 490 |
# File 'lib/jimmu.rb', line 487 def extract_boundary(content_type) return nil unless content_type content_type[/boundary="?([^";]+)"?/, 1] end |
.parse_json(raw_body) ⇒ Object
432 433 434 435 436 437 438 |
# File 'lib/jimmu.rb', line 432 def parse_json(raw_body) return {} if raw_body.nil? || raw_body.empty? data = JSON.parse(raw_body.dup.force_encoding(Encoding::UTF_8), symbolize_names: true) data.is_a?(Hash) ? data : { _json: data } rescue JSON::ParserError {} end |
.parse_multipart(raw_body, boundary) ⇒ Object
Returns [fields_hash, files_hash], both keyed by Symbol.
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
# File 'lib/jimmu.rb', line 441 def parse_multipart(raw_body, boundary) fields = {} files = {} return [fields, files] if raw_body.nil? || boundary.nil? || boundary.empty? body = raw_body.dup.force_encoding(Encoding::BINARY) delim = "--#{boundary}".b body.split(delim).each do |part| next if part.nil? || part.empty? next if part.start_with?('--'.b) part = part.sub(/\A\r\n/n, ''.b) part = part.sub(/\r\n\z/n, ''.b) next if part.empty? header_section, sep, body_section = part.partition("\r\n\r\n".b) next if sep.empty? headers = {} header_section.split("\r\n".b).each do |line| k, v = line.split(':'.b, 2) next unless k && v headers[k.strip.downcase] = v.strip end disposition = headers['content-disposition'.b] next unless disposition name = disposition[/name="([^"]*)"/n, 1] || disposition[/name=([^;]*)/n, 1] next unless name name_sym = name.dup.force_encoding(Encoding::UTF_8).to_sym filename = disposition[/filename="([^"]*)"/n, 1] if filename content_type = (headers['content-type'.b] || 'application/octet-stream').dup.force_encoding(Encoding::UTF_8) files[name_sym] = UploadedFile.new(filename.dup.force_encoding(Encoding::UTF_8), content_type, body_section) else fields[name_sym] = body_section.dup.force_encoding(Encoding::UTF_8) end end [fields, files] end |
.parse_urlencoded(raw_body) ⇒ Object
421 422 423 424 425 426 427 428 429 430 |
# File 'lib/jimmu.rb', line 421 def parse_urlencoded(raw_body) str = raw_body.to_s.dup.force_encoding(Encoding::UTF_8) result = {} URI.decode_www_form(str, Encoding::UTF_8).each do |k, v| result[k.to_sym] = v end result rescue ArgumentError {} end |