Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 201
Cooper Avatar asked Dec 12 '13 23:12

Cooper


People also ask

What is a payload in webhook?

Webhook payloads contain the installation property when the event is configured for and sent to a GitHub App. For more information, see "Building GitHub App." The unique properties for a webhook event are the same properties you'll find in the payload property when using the Events API. One exception is the push event.

Is a webhook URL a secret?

Webhook configuration requires selection of a target channel, reducing the scope of abuse to a single channel. The unique webhook URL is secret. The webhook only accepts data, and thus alone cannot expose sensitive data to third parties.

What is webhook URL?

Webhooks are automated messages sent from apps when something happens. They have a message—or payload—and are sent to a unique URL—essentially the app's phone number or address. Webhooks are almost always faster than polling, and require less work on your end. They're much like SMS notifications.


1 Answers

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.

like image 120
John Sheehan Avatar answered Oct 11 '22 17:10

John Sheehan