README.md

# PlugMultipartRelated

Parses multipart/related request body.

This is a partial implementation of RFC2387. This implementation is
heavily influence by `Plug.Parsers.MULTIPART` which is shipped with Plug.

The following choices have been made regarding support for the RFC2387
specification:
* start-info parameter - The start-info parameter is ignored if specified.
* If no start parameter is given the first MIME part is marked as the root
  part.
* The Content-ID part header is REQUIRED for each part. If Content-ID is not
  present the part will be ignored.
* Content-Disposition is used to create `Plug.Upload` structs in the output

A HTTP request with the following Content-Type header and body:
```
Content-Type: multipart/related; type="application/soap+xml"; boundary=----w58EW1cEpjzydSCq; start="part1"
```

```
------w58EW1cEpjzydSCq\r
Content-Disposition: form-data; name=\"info\"; filename=\"foo.txt\"\r
Content-ID: part1\r
Content-Type: text/plain\r
\r
bar
\r
------w58EW1cEpjzydSCq\r
Content-ID: part2\r
Content-Type: text/plain\r
\r
foobar\r
------w58EW1cEpjzydSCq\r
Content-Type: text/plain\r
\r
ignored\r
------w58EW1cEpjzydSCq--\r
```
Will be available in `Plug.Conn` as follows:
```
%{
  "part1" => %{
    "body" => %Plug.Upload{
      content_type: "text/plain",
      filename: "foo.txt",
      path: "/var/folders/hf/pd3rksm54wj6hfznxz9tv36c0000gn/T//plug-1540/multipart-1540203239-599604070647209-1"
    },
    "start" => true
},
  "part2" => %{
    "body" => "foobar"
  }
}
```
## Options

All options supported by `Plug.Conn.read_body/2` are also supported here.
They are repeated here for convenience:

  * `:length` - sets the maximum number of bytes to read from the request,
    defaults to 8_000_000 bytes
  * `:read_length` - sets the amount of bytes to read at one time from the
    underlying socket to fill the chunk, defaults to 1_000_000 bytes
  * `:read_timeout` - sets the timeout for each socket read, defaults to
    15_000ms

So by default, `Plug.Parsers` will read 1_000_000 bytes at a time from the
socket with an overall limit of 8_000_000 bytes.

Besides the options supported by `Plug.Conn.read_body/2`, the multipart parser
also checks for `:headers` option that contains the same `:length`, `:read_length`
and `:read_timeout` options which are used explicitly for parsing multipart
headers.

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `plug_multipart_related` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:plug_multipart_related, "~> 0.1.0"}
  ]
end
```

Configure in a Phoenix.Endpoint for example:
```
plug Plug.Parsers,
  parsers: [PlugMultipartRelated],
  pass: ["multipart/related"],
  read_length: 500_000, length: 4_000_000
```

Documentation can be found at [https://hexdocs.pm/plug_multipart_related](https://hexdocs.pm/plug_multipart_related).