Skip to main content
The First Step
January 13, 2023
Question

Webhook subscription is triggering with no body

Hi, We are recieving no body in webhook trigger from a subcription to telephony presence
/restapi/v1.0/account/~/extension/~/presence?detailedTelephonyState=true.
Note that this was working fine till yesterday and we haven't touched anything.

Are there any recent changes that might have caused this? How should I verify that my webhook url is recieving all the data in body that I need.

17 replies

PhongVu
Community Manager
Community Manager
January 14, 2023

I don't know what causes this, but I don't think that it is an actual telephony event trigger. I face the same issue with other event types and this is how I check and ignore such empty body (in Node JS code)

...
var body = []
req.on('data', function(chunk) {
  body.push(chunk);
}).on('end', function() {
  body = Buffer.concat(body).toString();
  if (!body || body == ""){
     console.log("Raw body: ", body)
     return
  }
  ...
New Participant
January 17, 2023

I encountered the same problem starting a few days ago. It turned out that the webhooks are now being sent with Transfer-Encoding: chunked, which means there is no content-length header. We were looking for content-length > 0 to see if there was a message body to read, otherwise assuming it was the initial validation request. I just had to change it to always read the content body -- the web framework will handle the transfer encoding, and we'll get back an empty string if there is no body.

The First Step
January 23, 2023

@Phong Vu @Andrew Gaskill By the time I got your response, issue was resolved without me doing anything, webhook started sending out body as well.

But now issue has resurfaced again. I am getting multiple triggers from webhook for single call and the request has no body. I also tried to read the chunked body as suggested above, but content is also empty from request.
How can I resolve my issue, is there a standard documentation for handling Transfer-Encoding:"chunked" request from ringcentrall?

New Participant
January 23, 2023

Hi @IT Team , it will depend on your web framework. We use ASP.Net Core, so we just read the content body as

using var reader = new StreamReader(req.Body, Encoding.UTF8);
var content = await reader.ReadToEndAsync();

and then check to see if the content is empty or can be parsed as JSON. The transfer encoding is handled automatically.

Likewise if you are using node.js with express, you would use the `express.json()` middleware to transparently handle reading the content body as JSON data, and again the transfer-encoding is handled automatically.


PhongVu
Community Manager
Community Manager
January 23, 2023

And one more note to this. As you know that your Webhook URL is publicly accessible, meaning that if anyone knows the URL address, they can post whatever data to the address. To enhance and prevent such a situation where you may get fake/invalid events from unknown sources, use the verification-token to verify the integrity of the source of a post.

{
  eventFilters: [ '/restapi/v1.0/account/~/telephony/sessions' ],
  deliveryMode: {
    transportType: 'WebHook',
    address: 'https://f5c8-69-181-XXX-YY.ngrok.io/webhookcallback',
    verificationToken: 'ThisIsMySecrettoken'
  },
  expiresIn: 3600000
}
REQ HEADERS:  {
  host: 'f5c8-69-181-XXX-YY.ngrok.io',
  'user-agent': 'RingCentral-WebHook/8.3',
  'content-length': '0',
  accept: 'application/json',
  'accept-encoding': 'UTF-8',
  'content-type': 'application/json; charset=UTF-8',
  'validation-token': 'dd64fe80-cbab-4529-94ce-d52e087250dc',
  'verification-token': 'ThisIsMySecrettoken',
  'x-forwarded-for': '199.255.122.132',
  'x-forwarded-proto': 'https'
}
The First Step
January 24, 2023

I think that I am having the same issue as @IT Team


I had a webhook setup in Azure that has been running fine since 2021, accepting event notifications from RingCentral using the /telephony/sessions filter. As of yesterday, it appears that the requests are coming through with no bodies or I don't know how to access the bodies properly in their new form. The webhook is an Azure function app written in Node.js. I don't actually know javascript, I just knocked up the original webhook from code samples and a bunch of trial and error, so I don't really have the know how to take @Andrew Gaskill 's solution and potentially make it work for my situation. Does anybody have any suggestions for how I should alter my code to be able to access the data that contains the actual telephony sessions?


module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    if (req.query.name) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.query.name)
        };
        context.bindings.outputQueueItem = req.body;
        context.log('200');
        context.log(req);
        context.done();
    }
    if (req.body  && req.body.uuid ) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.uuid )
        };
        context.bindings.outputQueueItem = req.body;
        context.log('200');
        context.log(req);
        context.done();
    }
    if ( req.url && req.headers['validation-token'] ) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            headers: {"Validation-Token": req.headers['validation-token']},
            body: "Hello " + (req.url)
           
        };
        context.bindings.outputQueueItem = req.body;
        context.log('200');
        context.log(req);
        context.done();
    }
    if ( req.url && req.headers['verification-token'] ) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            headers: {"Validation-Token": req.headers['verification-token']},
            body: "Hello " + (req.url)
           
        };
        context.bindings.outputQueueItem = req.body;
        context.log('200');
        context.log(req);
        context.done();
    }
    if ( req.url ) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " 
           
        };
        context.bindings.outputQueueItem = req.body;
        context.log('200');
        context.log(req);
        context.done();
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
        context.log('400');
        context.log(req);
        context.done();
    }
};
New Participant
January 24, 2023

@prospect-health Looks to be a longstanding issue with Azure Functions nodejs runtime:

https://github.com/Azure/azure-functions-nodejs-worker/issues/524

Another thread linked from that thread suggests that adding a configuration property to hosts.json might fix it, but that might only be for specific functions runtime versions:

https://github.com/Azure/azure-functions-host/issues/4926#issuecomment-888600059


The First Step
January 25, 2023

Thanks for looking into that for me. I think that looks like a rabbit hole too far for an amateur like me to dig into. I'm going to try setting up my subscriptions with PubNub via the RingCentral SDK and hopefully that will be robust enough for my needs.

The First Step
January 27, 2023

Seems like we cannot get access to the chunked request when using php/apache because of a bug with apache. Does anyone know of a workaround that we can use without changing the configuration of our server? I've been beating my head against the wall for two days now!

Our current process is when we get a request from RingCentral without a body, we get faxes from the RC API, iterate through the response, check for ones that we haven't downloaded, etc.

https://www.jeffgeerling.com/blog/2017/apache-fastcgi-proxyfcgi-and-empty-post-bodies-chunked-transfer

The First Step
January 30, 2023

Switching to Nginx seems to fix things for us which I looked into after reading this:

https://www.jeffgeerling.com/blog/2017/apache-fastcgi-proxyfcgi-and-empty-post-bodies-chunked-transfer

Running PHP on Apache, we sometimes would get a request with the content-length header -- but not the transfer-encoding header -- and we could easily get the contents of the request

{
  "content-length": "1081"
  "user-agent": "RingCentral-WebHook",
  "accept-encoding": "UTF-8",
  "accept": "application/json",
  "content-type": "application/json; charset=UTF-8",
  "verification-token": "xxx",
  "connection": "close
}


And sometimes get a request with the transfer-encoding header -- but not the content-length header -- and we were unable to get the contents of the request

{
  "transfer-encoding": "chunked",
  "user-agent": "RingCentral-WebHook",
  "accept-encoding": "UTF-8",
  "accept": "application/json",
  "content-type": "application/json; charset=UTF-8",
  "verification-token": "xxx",
  "connection": "close"
}


When testing on Nginx, the headers now include both the transfer-encoding and content-length header and we are able to get the body of the request as we did before (shrugs)

{
  "transfer-encoding": "chunked",
  "user-agent": "RingCentral-WebHook",
  "accept-encoding": "UTF-8",
  "accept": "application/json",
  "content-type": "application/json; charset=UTF-8",
  "verification-token": "xxx",
  "connection": "close",
  "content-length": "1081"
}