Skip to content

Instantly share code, notes, and snippets.

@wader
Created January 3, 2014 18:28
Show Gist options
  • Save wader/8243459 to your computer and use it in GitHub Desktop.
Save wader/8243459 to your computer and use it in GitHub Desktop.
Parse multipart byte ranges mime
# multipart byte ranges mime -> [[offset, content], ...]
def parse_multipart_byteranges(body, content_type)
# match boundary=...
match = /boundary=(.*)$/.match(content_type)
return nil if match.nil?
boundary = match[1]
# (\r\n)--boundary\r\npart\r\n--boundary(--)\r\n -> [part, ..]
parts = body.split(/(?:\r\n)?--#{boundary}(?:--)?\r\n/)
ranges = []
total_length = 0
parts.each do |part|
# filter out empty parts
next if /\A\s*\Z/.match(part)
# key: value\r\nkey: value\r\n\r\nbody -> [key: value, body]
part_header, part_body = part.split("\r\n\r\n", 2)
return nil if part_body.nil?
# key: value\r\n -> {key: value}
headers = Hash[part_header.lines.map do |line|
line.strip!
key, value = line.split(/:\s*/, 2)
return nil if value.nil?
[key.downcase, value]
end]
content_range = headers["content-range"]
return nil if content_range.nil?
# match bytes offset-length/total_length
match = /^bytes (\d+)-(\d+)\/(\d+)$/.match(content_range)
return nil if match.nil?
offset, length, total_length = match[1].to_i, match[2].to_i, match[3].to_i
ranges << [offset, part_body[0,length]]
end
return ranges, total_length
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment