Fl4m3Ph03n1x

Fl4m3Ph03n1x

How to use Plug.Parsers?

Background

I have a Plug Router that has some simple endpoints. One of these endpoints is a put method that receives a JSON body. I want to use Plug.Parsers to decode the body before processing it but I am having errors and I don’t know why.

Code

This is my router. Requests come here to be dispatched:

defmodule Api do
  use Plug.Router

  plug :match
  plug Plug.Parsers, parsers: [:urlencoded, :json],
    json_decoder: Jason
  plug :dispatch

  put "/cars"    do
    IO.inspect conn
    Conn.send_resp(conn, Status.code(:ok), "OK")
  end

end

To exercise this code, I have the following test:

    test "returns 200 OK when the list of cars is loaded correctly" do
      # Arrange
      body_params = "[
        {
          \"id\": 1,
          \"number\": 4
        },
        {
          \"id\": 2,
          \"number\": 6
        }
      ]"

      conn =
        :put
        |> conn("/cars")
        |> put_req_header("accept", "application/json")
        |> put_req_header("content-type", "application/json")
        |> put_body_params(body_params)

      # Act
      conn = Api.call(conn, @opts)

      # Assert
      assert conn.state == :sent
      assert conn.status == 200
      assert conn.resp_body == "OK"
    end

According to my knowledge, this should work, but I get the following error:

test PUT /cars returns 200 OK when the list of cars is loaded correctly (ApiTest)
test/api_test.exs:69
** (BadMapError) expected a map, got: “[\n {\n "id": 1,\n "number": 4\n },\n {\n "id": 2,\n "number": 6\n }\n ]”
code: conn = Api.call(conn, @opts)
stacktrace:
(stdlib 3.10) :maps.merge(%{}, “[\n {\n "id": 1,\n "seats": 4\n },\n {\n "id": 2,\n "seats": 6\n }\n ]”)
(plug 1.10.4) lib/plug/parsers.ex:354: Plug.Parsers.merge_params/4
(plug 1.10.4) lib/plug/parsers.ex:299: Plug.Parsers.call/2
(api 0.1.0) lib/api.ex:1: Api.plug_builder_call/2
test/api_test.exs:91: (test)

Questions

  1. Is my configuration of the router incorrect?
  2. Will the parser be applied to all incoming requests?
  3. What happens if I get a request that is not JSON? (will the parser ignore it?)
  4. What am I doing wrong?

Marked As Solved

al2o3cr

al2o3cr

Using put_body_params entirely short-circuits the parsing in Plug.Parser - that only happens when body_params is a %Plug.Unfetched{}.

You want to set the body to the unparsed JSON when calling Plug.Test.conn/3:

conn(:put, "/cars", body_params_json_string)
|> put_request_header("content-type", "application/json")
|> put_request_header("accept", "application/json")

Where Next?

Popular in Questions Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement