# module MIME::Multipart

##
Overview

The `MIME::Multipart` module contains utilities for parsing MIME multipart messages, which contain multiple body parts, each containing a header section and binary body. The `multipart/form-data` content-type has a separate set of utilities in the `HTTP::FormData` module.

##
Defined in:

mime/multipart.cr
mime/multipart/builder.cr
mime/multipart/parser.cr
mime/multipart/state.cr

##
Class Method Summary

- .build(io : IO, boundary : String = Multipart.generate_boundary, &)

  Yields a `Multipart::Builder` to the given block, writing to io and using boundary.

- .build(boundary : String = Multipart.generate_boundary, &)

  Yields a `Multipart::Builder` to the given block, returning the generated message as a `String`.

- .generate_boundary : String

  Returns a unique string suitable for use as a multipart boundary.

- .parse(io, boundary, &)

  Parses a MIME multipart message, yielding `HTTP::Headers` and an `IO` for each body part.

- .parse(request : HTTP::Request, &)

  Parses a MIME multipart message, yielding `HTTP::Headers` and an `IO` for each body part.

- .parse(response : HTTP::Client::Response, &)

  Parses a MIME multipart message, yielding `HTTP::Headers` and an `IO` for each body part.

- .parse_boundary(content_type : String) : String | Nil

  Extracts the multipart boundary from the Content-Type header.

##
Class Method Detail

def self.build(io : IO, boundary : String = Multipart.generate_boundary, &) #

Yields a `Multipart::Builder` to the given block, writing to io and using boundary. `#finish` is automatically called on the builder.

def self.build(boundary : String = Multipart.generate_boundary, &) #

Yields a `Multipart::Builder` to the given block, returning the generated message as a `String`.

def self.generate_boundary : String #

Returns a unique string suitable for use as a multipart boundary.

    require "mime/multipart"

    MIME::Multipart.generate_boundary # => "---------------------------dQu6bXHYb4m5zrRC3xPTGwV"

def self.parse(io, boundary, &) #

Parses a MIME multipart message, yielding `HTTP::Headers` and an `IO` for each body part.

Please note that the IO object yielded to the block is only valid while the block is executing. The IO is closed as soon as the supplied block returns.

    require "mime/multipart"

    multipart = "--aA40\r\nContent-Type: text/plain\r\n\r\nbody\r\n--aA40--"
    MIME::Multipart.parse(IO::Memory.new(multipart), "aA40") do |headers, io|
      headers["Content-Type"] # => "text/plain"
      io.gets_to_end          # => "body"
    end

See: `Multipart::Parser`

def self.parse(request : HTTP::Request, &) #

Parses a MIME multipart message, yielding `HTTP::Headers` and an `IO` for each body part.

Please note that the IO object yielded to the block is only valid while the block is executing. The IO is closed as soon as the supplied block returns.

    require "http"
    require "mime/multipart"

    headers = HTTP::Headers{"Content-Type" => "multipart/mixed; boundary=aA40"}
    body = "--aA40\r\nContent-Type: text/plain\r\n\r\nbody\r\n--aA40--"
    request = HTTP::Request.new("POST", "/", headers, body)

    MIME::Multipart.parse(request) do |headers, io|
      headers["Content-Type"] # => "text/plain"
      io.gets_to_end          # => "body"
    end

See: `Multipart::Parser`

def self.parse(response : HTTP::Client::Response, &) #

Parses a MIME multipart message, yielding `HTTP::Headers` and an `IO` for each body part.

Please note that the IO object yielded to the block is only valid while the block is executing. The IO is closed as soon as the supplied block returns.

    require "http"
    require "mime/multipart"

    headers = HTTP::Headers{"Content-Type" => "multipart/byteranges; boundary=aA40"}
    body = "--aA40\r\nContent-Type: text/plain\r\n\r\nbody\r\n--aA40--"
    response = HTTP::Client::Response.new(
      status: :ok,
      headers: headers,
      body: body,
    )

    MIME::Multipart.parse(response) do |headers, io|
      headers["Content-Type"] # => "text/plain"
      io.gets_to_end          # => "body"
    end

See: `Multipart::Parser`

def self.parse_boundary(content_type : String) : String | Nil #

Extracts the multipart boundary from the Content-Type header. May return `nil` is the boundary was not found.

    require "mime/multipart"

    MIME::Multipart.parse_boundary("multipart/mixed; boundary=\"abcde\"") # => "abcde"