Skip to content

Commit

Permalink
Support Webhooks as rule actions
Browse files Browse the repository at this point in the history
The difference to normal rule actions is the address which is the
full (arbitrary) URL starting with http:// or https://
  • Loading branch information
manup committed May 6, 2019
1 parent 2e08a88 commit d57e88d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
4 changes: 4 additions & 0 deletions de_web_plugin.cpp
Expand Up @@ -292,6 +292,10 @@ DeRestPluginPrivate::DeRestPluginPrivate(QObject *parent) :
gwAnnounceUrl = "http://dresden-light.appspot.com/discover";
inetDiscoveryManager = 0;

webhookManager = new QNetworkAccessManager(this);
connect(webhookManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(webhookFinishedRequest(QNetworkReply*)));

// lights
searchLightsState = SearchLightsIdle;
searchLightsTimeout = 0;
Expand Down
5 changes: 5 additions & 0 deletions de_web_plugin_private.h
Expand Up @@ -927,6 +927,7 @@ class DeRestPluginPrivate : public QObject
void indexRuleTriggers(Rule &rule);
void triggerRule(Rule &rule);
bool ruleToMap(const Rule *rule, QVariantMap &map);
int handleWebHook(const RuleAction &action);

bool checkActions(QVariantList actionsList, ApiResponse &rsp);
bool checkConditions(QVariantList conditionsList, ApiResponse &rsp);
Expand Down Expand Up @@ -1029,6 +1030,7 @@ public Q_SLOTS:
void verifyRuleBindingsTimerFired();
void indexRulesTriggers();
void fastRuleCheckTimerFired();
void webhookFinishedRequest(QNetworkReply *reply);
void daylightTimerFired();
void handleRuleEvent(const Event &e);
bool queueBindingTask(const BindingTask &bindingTask);
Expand Down Expand Up @@ -1489,6 +1491,9 @@ public Q_SLOTS:
QTimer *scheduleTimer;
std::vector<Schedule> schedules;

// webhooks
QNetworkAccessManager *webhookManager = nullptr;

// internet discovery
QNetworkAccessManager *inetDiscoveryManager;
QTimer *inetDiscoveryTimer;
Expand Down
52 changes: 49 additions & 3 deletions rest_rules.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 dresden elektronik ingenieurtechnik gmbh.
* Copyright (c) 2016-2019 dresden elektronik ingenieurtechnik gmbh.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand All @@ -12,6 +12,8 @@
#include <QVariantMap>
#include <QRegExp>
#include <QStringBuilder>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "de_web_plugin.h"
#include "de_web_plugin_private.h"
#include "json.h"
Expand Down Expand Up @@ -843,6 +845,11 @@ bool DeRestPluginPrivate::checkActions(QVariantList actionsList, ApiResponse &rs

for (int i = 0; ; i++)
{
if (address.startsWith(QLatin1String("http"))) // webhook http/https
{
break; // supported
}

if (!resources[i])
{
rsp.list.append(errorToMap(ERR_ACTION_ERROR, QString(address),
Expand Down Expand Up @@ -1513,9 +1520,21 @@ void DeRestPluginPrivate::triggerRule(Rule &rule)

for (; ai != aend; ++ai)
{
if (ai->method() != QLatin1String("PUT"))
// check webhook
if (ai->address().startsWith(QLatin1String("http")))
{
if (handleWebHook(*ai) == REQ_NOT_HANDLED)
{
return;
}
triggered = true;
continue;
}

if (ai->method() != QLatin1String("PUT") && ai->method() != QLatin1String("POST"))
return;


QStringList path = ai->address().split(QChar('/'), QString::SkipEmptyParts);

if (path.isEmpty()) // at least: /config, /groups, /lights, /sensors
Expand All @@ -1527,7 +1546,7 @@ void DeRestPluginPrivate::triggerRule(Rule &rule)
path.prepend(rule.owner()); // apikey
path.prepend(QLatin1String("api")); // api

ApiRequest req(hdr, path, NULL, ai->body());
ApiRequest req(hdr, path, nullptr, ai->body());
ApiResponse rsp;
rsp.httpStatus = HttpStatusServiceUnavailable;

Expand Down Expand Up @@ -1595,6 +1614,33 @@ void DeRestPluginPrivate::triggerRule(Rule &rule)
}
}

/*! Sends a HTTP request aka webhook based on a rule action.
\param action - the action holding the request details
*/
int DeRestPluginPrivate::handleWebHook(const RuleAction &action)
{
QNetworkRequest req(QUrl(action.address()));

if (webhookManager->sendCustomRequest(req, action.method().toUtf8(), action.body().toUtf8()) != nullptr)
{
return REQ_READY_SEND;
}

return REQ_NOT_HANDLED;
}

/*! Handler for finished webhooks.
*/
void DeRestPluginPrivate::webhookFinishedRequest(QNetworkReply *reply)
{
if (!reply)
{
return;
}

reply->deleteLater();
}

/*! Verifies that rule bindings are valid. */
void DeRestPluginPrivate::verifyRuleBindingsTimerFired()
{
Expand Down

0 comments on commit d57e88d

Please sign in to comment.