Packages

A heavy WIP library for streaming multipart data.

Current section

Files

Jump to
mupex lib mupex.ex
Raw

lib/mupex.ex

defmodule Mupex do
import Plug.Conn
def next_headers(conn, opts \\ []) do
opts = Keyword.merge(config(:headers), opts)
parse_headers(read_part_headers(conn, opts))
end
def next_body(conn, opts \\ []) do
opts =
Keyword.merge(config(), opts)
|> Keyword.delete(:headers)
start_fun = fn -> {read_part_body(conn, opts), opts} end
next_fun = &stream_body/1
after_fun = fn _x -> nil end
Stream.resource(start_fun, next_fun, after_fun)
end
defp config, do: Application.get_env(:mupex, Mupex)
defp config(key), do: Application.get_env(:mupex, Mupex)[key]
defp stream_body({{:more, tail, conn}, opts}) do
{[{:data, tail, conn}], {read_part_body(conn, opts), opts}}
end
defp stream_body({{:ok, tail, conn}, opts}) do
{[{:data, tail, conn}], {{:done, conn}, opts}}
end
defp stream_body({{:done, conn}, opts}) do
{[{:done, conn}], {{:halt, conn}, opts}}
end
defp stream_body({{:halt, _conn}, _opts}), do: {:halt, nil}
defp parse_headers({:ok, mp_headers, conn}) do
{name, params, content_type} = multipart_type(mp_headers)
{:ok, name, params, content_type, conn}
end
defp parse_headers({:done, conn}) do
{:done, conn}
end
defp multipart_type(mp_headers) do
with {_, disposition} <- List.keyfind(mp_headers, "content-disposition", 0),
[_, params] <- :binary.split(disposition, ";"),
%{"name" => name} = params <- Plug.Conn.Utils.params(params) do
handle_disposition(params, name, mp_headers)
else
_ -> :skip
end
end
defp handle_disposition(params, name, mp_headers) do
{name, Map.delete(params, "name"), get_header(mp_headers, "content-type")}
end
defp get_header(headers, key) do
case List.keyfind(headers, key, 0) do
{^key, value} -> value
nil -> nil
end
end
end