roccomuso / node-webhooks

:arrow_right_hook: Node.js module to create and trigger your own webHooks.
190 stars 47 forks source link

webHook does not carry json payload #18

Closed cosiwankenobi closed 6 years ago

cosiwankenobi commented 6 years ago

hi, I'm trying using WebHooks to call a php rest on localhost when an alarm is triggered. The WebHook calls the rest, but there is no json payload in the request. Here are the data about http headers catched by my php rest:

Content-Type:application/json host:localhost content-length:0 Connection:close

also the data readed by the following instructions: $request_body = file_get_contents('php://input'); $data = json_decode($request_body); results empty

roccomuso commented 6 years ago

Paste also your JS code.

cosiwankenobi commented 6 years ago

I registered the webHook by this code:

var xhr = new XMLHttpRequest();
var data = JSON.stringify({"url": "http://localhost/putonlight.php"});

xhr.open('POST', 'http://localhost:8080/api/webhook/add/alarmTriggered', true);
xhr.setRequestHeader('Access-Control-Allow-Headers', '*');
xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
xhr.setRequestHeader('Authorization',       'Basic cm9vdDpyb290');
xhr.setRequestHeader("Content-type", "application/json");
xhr.withCredentials = true;
xhr.send(data);

xhr.onreadystatechange = processRequest;

function processRequest(e) {
     if (xhr.readyState == 4) {
         var response = JSON.parse(xhr.responseText);
         alert(xhr.responseText);
      }
}

and then, in .php file, I simply read headers and content and write them on a log file:

foreach (getallheaders() as $name => $value) {
    $message= "$name: $value";
    fwrite($f, $message . chr(13));
}  //cicla per ciascun header e lo scrive sul file

$request_body = file_get_contents('php://input');
$data = json_decode($request_body);  
fwrite($f,"data: " . $data . chr(13)); //legge il payload e lo scrive sul file
roccomuso commented 6 years ago
  1. Do not use the raw xhr request. Now modern browsers has the .fetch() method. Google it.
  2. This is the client side. node-webhooks is meant to be run server-side with node.js.
  3. Are you running an express server on the port 8080 ? Paste the code then.
  4. The php file is the one that run on port 80?
  5. the data payload should be sent when triggering the webhook, not when istantiating it.
cosiwankenobi commented 6 years ago

I'm sorry, I'll try to explain better. I'm running iot-433mhz server on port 8080 and apache/php server on port 80.

I registered a sensor as alarm card by iot-433mhz console and armed it.

Then I used the API call (JS client code I pasted) to register an url to the webHook 'alarmTriggered'. I ran that code only once and I think it worked. In fact, when I query the webHooks archive via API '/api/webhook/get' I obtain: {"status":"OK","data":{"alarmTriggered":["http://localhost/putonlight.php"]}}

putonlight.php is the php file running on port 80. It manage the actions to be taken when an alarm is triggered. But first it must check which alarm is triggered.

When the sensor trigger the alarm, 'http://localhost/putonlight.php' is actually called. Accordingly with API documentation, I'm expecting to receive a json payload with this format: 'alarmTriggered = {"card_id": "...", "last_alert": 1453..., "code": ..., "shortname": "...", "room": "..." }'

But there is no POST data nor json body content.

roccomuso commented 6 years ago

Try launching iot-433mhz with the env-var DEBUG=node-webhooks. Maybe we'll see some useful info on console.

Moreover, did you try a simple POST call to your apache server to make sure you can see data into POST requests?

cosiwankenobi commented 6 years ago

The console debut infos are: node-webhooks POST request to: http://localhost/putonlight.php +26m node-webhooks Request sent - Server responded with: 200 null +4ms

I made an html page to call http://localhost/putonlight.php and POST a json to it. When the html page is located under port 80 (e.g. http://localhost/send-json.html), http://localhost/putonlight.php receive the json. When the html page is located in the iot-433mhz/www/ folder (and the port is 8080, e.g. http://localhost:8080/send-json) http://localhost/putonlight.php does not receive the json.

Somewhere in the passage from the server on port 8080 to the server on port 80 the post data are deleted, but I can't figure where.

roccomuso commented 6 years ago

The issue might be your apace/php server then.

Try spawning this node server instead of yours and let's see:

var http = require('http')
var server = http.createServer( function(req, res) {
    if (req.method == 'POST') {
        console.log("POST");
        var body = '';
        req.on('data', function (data) {
            body += data;
        });
        req.on('end', function () {
            console.log("Body: " + body);
        });
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('post received');
    } else { console.log('This is not a POST', req.method) }
})

server.listen(80)

sudo node index.js

This server listen on port 80 and should print the POST payload on console.

cosiwankenobi commented 6 years ago

I tried the node server you suggest. The output on console is:

POST Body:

On iot-433mhz console the output is "Request sent - Server responded with: 200 post received"

I tried also to install iot-433mhz on a windows system with IIS running my php rest instead of Apache, but the result is always the same.

roccomuso commented 6 years ago

ok, we could have a bug then. It's not sending the payload pheraps.

Did you install the iot-433mhz globally? Then lets put a console.log('PAYLOAD:', card) before this line: components/notification.js#L70 and restart iot-433mhz. The file should be located here /usr/local/lib/node_modules/iot-433mhz/components/notification.js

We should see in console if the payload is passed with success to the webhook trigger function.

You can also edit this log call to improve node-webhooks debug info. This file is inside the node-webhooks folder into the iot-433mhz node_modules dir.

cosiwankenobi commented 6 years ago

ok, i tried. console.log('PAYLOAD:', card) throws an exception because card is null:

TypeError: Cannot read property 'toString' of undefined
    at C:\Users\xxx\AppData\Roaming\npm\node_modules\iot-433mhz\node_modules\console-mirroring\console.mirroring.js:24:21
    at Array.map (<anonymous>)
    at Console.log (C:\Users\xxx\AppData\Roaming\npm\node_modules\iot-433mhz\node_modules\console-mirroring\console.mirroring.js:20:27)
    at C:\Users\xxx\AppData\Roaming\npm\node_modules\iot-433mhz\components\notification.js:70:13
    at new Promise (<anonymous>)
    at adviceWebHook (C:\Users\xxx\AppData\Roaming\npm\node_modules\iot-433mhz\components\notification.js:68:11)
    at <anonymous>

So i removed it and add debug('Send json: ',jsonData) on line 105 of node-webhooks/index.js The output is (i'm trying just sending json to node server you suggested me to create on port 80):

node-webhooks POST request to: http://localhost/ +8s
node-webhooks Send json:  undefined +5ms
node-webhooks Request sent - Server responded with: 200 post received +59ms

This is the card i registered for the alarm: [{"active":true,"date":1522177610,"headline":"alarm1","shortname":"alarm1","card_body":"alarm1","background_color":"#FAFAFA","img":false,"room":"test","type":"alarm","device":{"last_alert":1522179287,"notification_sound":true,"armed":true,"trigger_code":17748},"_id":"qntYHn62YLd8vzY2"}]

roccomuso commented 6 years ago

Sorry, do not put console.log but debug('PAYLOAD:', card) instead and start iot-433mhz with debug enabled. Moreover, which version of node did you install? node -v And which version of iot-433mhz ?

cosiwankenobi commented 6 years ago

Now debug output is: iot-433mhz:index.js Code already exists in DB +15ms iot-433mhz:index.js code available: false assigned to: alarm1 +0ms iot-433mhz:index.js Telegram Notification disabled. Menu > Settings. +0ms iot-433mhz:index.js PAYLOAD: undefined +0ms iot-433mhz:index.js RFcode received: { type: 'signal', status: 'received', code: 17748, bitlength: 24, protocol: 1 } +7s

node version: 8.10.0 iot-433mhz version: 1.0.37 installed via npm

roccomuso commented 6 years ago

I should've found the bug. Now it should be fixed with the latest iot-433mhz v1.0.4.

I've also bumped many dependencies. Please reinstall everything and let me know.

cosiwankenobi commented 6 years ago

Now it works! Thank you so much!