Cooper
Cooper

Reputation: 866

Should webhook JSON payloads be URL encoded?

New Relic currently URL encodes the JSON payload of our webhooks. We correctly include the necessary header, however, I'm wondering if this is best practice - or if the JSON payload should be sent un-encoded (or even with some different encoding)?

enter image description here

Upvotes: 5

Views: 3849

Answers (2)

Matt
Matt

Reputation: 911

<rant>

Payloads should be the content type you say they are. If they are sending as application/x-www-form-urlencoded then that is what you should expect to find. The culture of using a Russian doll model of nested encodings is beyond stupid in my opinion.

If you want to send JSON send it as application/json. Is that really so hard?

</rant>

Upvotes: 2

John Sheehan
John Sheehan

Reputation: 78152

It's more common to send JSON directly in the request body with a Content-Type header value of application/json. It's not entirely uncommon to do it the way New Relic does however. GitHub post-receive hook payloads are also encoded this way.

In some languages/frameworks it's easier to extract the JSON data from a parameter than from reading the entire request body since form parameters are automatically parsed out and easily referenced and in some cases reading a request body may involve some more elaborate stream parsing.

An example of that is PHP's syntax for extracting the entire raw request body:

$data = file_get_contents('php://input');
var_dump(json_decode($data));

Versus extracting from a form parameter:

$data = $_POST["payload"];
var_dump(json_decode($data));

For frameworks that easily expose the request body, this isn't as much an issue. Here's the example given from the GitHub docs for handling the hook with Sinatra:

post '/' do
  push = JSON.parse(params[:payload])
  "I got some JSON: #{push.inspect}"
end

If the JSON body were passed directly, this is what it would look like:

post '/' do
  push = JSON.parse(request.body.read)
  "I got some JSON: #{push.inspect}"
end

It's mostly just an aesthetic preference, there's no technical advantage to either. With the parameter, you do get the flexibility of sending multiple JSON payloads in a single request or the option to send additional meta data outside the JSON. I would suggest sending a list of JSON objects and including all the meta data in a top level wrapper if that's important to you. Something like this:

{
    "notification_id": "akjfd8",
    "events": [ ... ]
}

I personally prefer raw JSON bodies, but that's mostly because it makes debugging far easier on sites like RequestBin. Your screenshot does a great job of illustrating how unreadable JSON encoded into a form parameter is.

Upvotes: 3

Related Questions