Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsing json payload of a webhook #15

Closed
SimonLab opened this issue Mar 8, 2017 · 14 comments
Closed

Parsing json payload of a webhook #15

SimonLab opened this issue Mar 8, 2017 · 14 comments

Comments

@SimonLab
Copy link
Member

SimonLab commented Mar 8, 2017

The server is now able to catch the payload sent by Github:

{
  "action": "created",
  "issue": {
    "url": "https://api.github.com/repos/dwyl/dwylbot/issues/9",
    "repository_url": "https://api.github.com/repos/dwyl/dwylbot",
    "labels_url": "https://api.github.com/repos/dwyl/dwylbot/issues/9/labels{/name}",
    "comments_url": "https://api.github.com/repos/dwyl/dwylbot/issues/9/comments",
    "events_url": "https://api.github.com/repos/dwyl/dwylbot/issues/9/events",
    "html_url": "https:/dwyl/dwylbot/pull/9",
...

and my controller has the following create action:

  def create(conn, %{"payload" => payload}) do
    IO.puts "Post request to /webhooks received!"

    IO.puts payload.action
    conn
    |> put_status(201)
    |> json(%{ok: true})

  end

I manage to print the payload but I fail to extract the "action" property with payload.action:

Request: POST /webhooks/create
** (exit) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.apply("{\"action\":\"labeled\",\"issue\":{\"url\"

I've also try to use a pattern match on the action with

  def create(conn, %{"payload" => %{"action" => action}}) do
    IO.puts "Post request to /webhooks received!"
    IO.puts action
    conn
    |> put_status(201)
    |> json(%{ok: true})

  end

but get also an error

(Phoenix.ActionClauseError) bad request to Dwylbot.WebhooksController.create, no matching action clause to process request

@Shouston3 @jackcarlisle do you have any suggestions on how to access the values of a json payload?

@jruts
Copy link
Member

jruts commented Mar 8, 2017

@SimonLab , can you try Map.get(payload, "action") ?
Or can you print out how the actual payload looks like? IO.puts "${inspect payload}" or IO.inspect payload

@SimonLab
Copy link
Member Author

SimonLab commented Mar 8, 2017

(BadMapError) expected a map, got: "{\"action\":\"created\",\"issue\":{\"url\":\"https://api.github.com/repos/dwyl/dwylbot/issues/9\",...

It looks the the payload still contains a string, is this right? I thought Phoenix could automatically parse a stringify json with Poison

@jruts
Copy link
Member

jruts commented Mar 8, 2017

Don't you need to explicitly decode it with Poison? Poison.decode! payload

@SimonLab
Copy link
Member Author

SimonLab commented Mar 8, 2017

@jruts Thanks a lot it worked! I try to see how I can add the decode function into the api pipeline to parse automatically the payload on each requests:

  pipeline :api do
    plug :accepts, ["json"]
   # plug :parsepayload or something similar
  end

@jruts
Copy link
Member

jruts commented Mar 8, 2017

@SimonLab you will indeed need a plug parser for that.
https://hexdocs.pm/plug/Plug.Parsers.html

more specifically: https://hexdocs.pm/plug/Plug.Parsers.JSON.html#content

@jruts
Copy link
Member

jruts commented Mar 8, 2017

@SimonLab a more detailed example: http://absinthe-graphql.org/guides/plug-phoenix/

Scroll over to the Phoenix section (ignore the absynthe bit)

@jruts
Copy link
Member

jruts commented Mar 8, 2017

@jruts
Copy link
Member

jruts commented Mar 8, 2017

Sorry for the ramble, I am pretty sure you can figure it out pretty easily by yourself! Good stuff :)

@SimonLab
Copy link
Member Author

SimonLab commented Mar 8, 2017

Thanks for all the links 👍 I'll read through the doc and try to understand the details of the parsers

@jruts
Copy link
Member

jruts commented Mar 8, 2017

@SimonLab a last tip: https://engineering.appcues.com/2016/02/02/too-many-dicts.html

Read 2 and 5 carefully. You will want to use a struct, not just decode the json string into a map.

Have fun :)

@SimonLab
Copy link
Member Author

SimonLab commented Mar 9, 2017

At the moment I parse the stringify payload with Poison.decode!(payload) in my create action. I'm still looking for another way to parse the json maybe by creating a Plug. Also the endpoint.ex file already parse the body of the requests see this line but the payload is still stringify so I'm still missing something and don't quiet yet understand how the payload is created from the post request.
Some more research to be done on this but at this stage it's not a blocker anymore

@jruts
Copy link
Member

jruts commented Mar 9, 2017

@iteles
Copy link
Member

iteles commented Mar 9, 2017

@jruts Thanks for all the input! 😍
You're a peach 🍑

SimonLab added a commit that referenced this issue Mar 10, 2017
@SimonLab
Copy link
Member Author

Thanks for all the links!! My main issue when parsing the payload was in fact a mistake from my part when I created the webhooks on Githbub, see #19 . Phoenix automatically parse the json payload to a map 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants