eddy147
January 13, 2023, 10:08am
1
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!
Maybe none? I mean, you can probably just read the request body with Plug.Conn.read_body/2 and parse it yourself?
1 Like
fuelen
January 13, 2023, 10:20am
3
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.
eddy147
January 13, 2023, 10:25am
4
Yes! read_body/2 does the trick!
Now at least I can see the body.
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.
adamu
January 14, 2023, 12:35pm
7
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