Which Plug.Parsers do I need to POST plain text?

I have a very minimalistic elixir app, without Phoenix, and I want to POST a text/csv, like

92831,"vin-12435"

So not as file, but as text in a body.

Without using any Plug.Parsers, conn.params stays empty and can not see the body.

If I use Plug’s json parser en parse the body with Poison and send the body as application/json, I do see the conn.params with the values.

But I have to send the data as csv, to minimize overhead, but I do not know which Plug.Parsers to use for that.

Thanks! :slightly_smiling_face:

Maybe none? I mean, you can probably just read the request body with Plug.Conn.read_body/2 and parse it yourself?

1 Like

According to docs, :parsers accepts a list of modules or atoms of built-in parsers. You can create your own parser by implementing Plug.Parsers behaviour.

Yes! read_body/2 does the trick!
Now at least I can see the body.
Thx.

nice tip, thx!

yeah, if it’s a repeated task of reading the CSV uploaded as body in multiple places in the app, I’d consider doing that.

Here’s a really simple one using NimbleCSV that you can use as a base and adjust as you need:

defmodule CSVPlugParser do
  @behaviour Plug.Parsers

  @impl true
  def init(_), do: []

  @impl true
  def parse(conn, "text", "csv", _params, _opts) do
    {:ok, body, conn} = Plug.Conn.read_body(conn)

    params =
      body
      |> NimbleCSV.RFC4180.parse_string(skip_headers: false)
      |> Map.new(&List.to_tuple/1)

    {:ok, params, conn}
  end
end

Using as part of a Plug app:

curl -H "content-type:text/csv" localhost:4000 --data '92831,"vin-12435"'
%{"92831" => "vin-12435"}
1 Like