From dcf9816a722160ad3ced406f5781839668fff9a4 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Thu, 23 Feb 2023 01:02:12 +0100 Subject: [PATCH] Add header support to http action --- data/locale/en-US.ini | 3 ++ src/macro-core/macro-action-http.cpp | 74 ++++++++++++++++++++++++---- src/macro-core/macro-action-http.hpp | 12 ++++- src/utils/curl-helper.cpp | 11 ++++- src/utils/curl-helper.hpp | 5 ++ 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 8eb68583..09938f24 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -592,6 +592,9 @@ AdvSceneSwitcher.action.websocket.type.event="Event" AdvSceneSwitcher.action.websocket.entry.request="Send scene switcher {{type}} via {{connection}}" AdvSceneSwitcher.action.websocket.entry.event="Send scene switcher {{type}} to connected clients" AdvSceneSwitcher.action.http="Http" +AdvSceneSwitcher.action.http.setHeaders="Set headers" +AdvSceneSwitcher.action.http.headers="Headers:" +AdvSceneSwitcher.action.http.addHeader="Add header" AdvSceneSwitcher.action.http.type.get="GET" AdvSceneSwitcher.action.http.type.post="POST" AdvSceneSwitcher.action.http.entry.line1="Send {{method}} to {{url}}" diff --git a/src/macro-core/macro-action-http.cpp b/src/macro-core/macro-action-http.cpp index 02a839e6..a37c41f8 100644 --- a/src/macro-core/macro-action-http.cpp +++ b/src/macro-core/macro-action-http.cpp @@ -27,11 +27,26 @@ size_t WriteCB(void *ptr, size_t size, size_t nmemb, std::string *buffer) return size * nmemb; } +void MacroActionHttp::SetupHeaders() +{ + if (!_setHeaders) { + return; + } + struct curl_slist *headers = nullptr; + for (auto &header : _headers) { + headers = switcher->curl.SlistAppend(headers, header.c_str()); + } + if (!_headers.empty()) { + switcher->curl.SetOpt(CURLOPT_HTTPHEADER, headers); + } +} + void MacroActionHttp::Get() { switcher->curl.SetOpt(CURLOPT_URL, _url.c_str()); switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L); switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000); + SetupHeaders(); std::string response; if (IsReferencedInVars()) { @@ -50,6 +65,7 @@ void MacroActionHttp::Post() switcher->curl.SetOpt(CURLOPT_URL, _url.c_str()); switcher->curl.SetOpt(CURLOPT_POSTFIELDS, _data.c_str()); switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000); + SetupHeaders(); switcher->curl.Perform(); } @@ -92,6 +108,8 @@ bool MacroActionHttp::Save(obs_data_t *obj) const MacroAction::Save(obj); _url.Save(obj, "url"); _data.Save(obj, "data"); + obs_data_set_bool(obj, "setHeaders", _setHeaders); + _headers.Save(obj, "headers", "header"); obs_data_set_int(obj, "method", static_cast(_method)); _timeout.Save(obj); return true; @@ -102,6 +120,8 @@ bool MacroActionHttp::Load(obs_data_t *obj) MacroAction::Load(obj); _url.Load(obj, "url"); _data.Load(obj, "data"); + _setHeaders = obs_data_get_bool(obj, "setHeaders"); + _headers.Load(obj, "headers", "header"); _method = static_cast(obs_data_get_int(obj, "method")); _timeout.Load(obj); return true; @@ -125,6 +145,12 @@ MacroActionHttpEdit::MacroActionHttpEdit( _url(new VariableLineEdit(this)), _methods(new QComboBox()), _data(new VariableTextEdit(this)), + _setHeaders(new QCheckBox( + obs_module_text("AdvSceneSwitcher.action.http.setHeaders"))), + _headerListLayout(new QVBoxLayout()), + _headerList(new StringListEdit( + this, obs_module_text("AdvSceneSwitcher.action.http.headers"), + obs_module_text("AdvSceneSwitcher.action.http.addHeader"))), _timeout(new DurationSelection(this, false)) { populateMethodSelection(_methods); @@ -137,6 +163,11 @@ MacroActionHttpEdit::MacroActionHttpEdit( SLOT(MethodChanged(int))); QWidget::connect(_timeout, SIGNAL(DurationChanged(double)), this, SLOT(TimeoutChanged(double))); + QWidget::connect(_setHeaders, SIGNAL(stateChanged(int)), this, + SLOT(SetHeadersChanged(int))); + QWidget::connect(_headerList, + SIGNAL(StringListChanged(const StringList &)), this, + SLOT(HeadersChanged(const StringList &))); std::unordered_map widgetPlaceholders = { {"{{url}}", _url}, @@ -153,8 +184,14 @@ MacroActionHttpEdit::MacroActionHttpEdit( obs_module_text("AdvSceneSwitcher.action.http.entry.line2"), timeoutLayout, widgetPlaceholders); + _headerListLayout->addWidget(new QLabel( + obs_module_text("AdvSceneSwitcher.action.http.headers"))); + _headerListLayout->addWidget(_headerList); + QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(actionLayout); + mainLayout->addWidget(_setHeaders); + mainLayout->addLayout(_headerListLayout); mainLayout->addWidget(_data); mainLayout->addLayout(timeoutLayout); setLayout(mainLayout); @@ -172,6 +209,8 @@ void MacroActionHttpEdit::UpdateEntryData() _url->setText(_entryData->_url); _data->setPlainText(_entryData->_data); + _setHeaders->setChecked(_entryData->_setHeaders); + _headerList->SetStringList(_entryData->_headers); _methods->setCurrentIndex(static_cast(_entryData->_method)); _timeout->SetDuration(_entryData->_timeout); SetWidgetVisibility(); @@ -209,18 +248,33 @@ void MacroActionHttpEdit::TimeoutChanged(double seconds) _entryData->_timeout.seconds = seconds; } +void MacroActionHttpEdit::SetHeadersChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_setHeaders = value; + SetWidgetVisibility(); +} + +void MacroActionHttpEdit::HeadersChanged(const StringList &headers) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_headers = headers; + adjustSize(); + updateGeometry(); +} + void MacroActionHttpEdit::SetWidgetVisibility() { - switch (_entryData->_method) { - case MacroActionHttp::Method::GET: - _data->hide(); - break; - case MacroActionHttp::Method::POST: - _data->show(); - break; - default: - break; - } + _data->setVisible(_entryData->_method == MacroActionHttp::Method::POST); + setLayoutVisible(_headerListLayout, _entryData->_setHeaders); adjustSize(); updateGeometry(); diff --git a/src/macro-core/macro-action-http.hpp b/src/macro-core/macro-action-http.hpp index d4cea026..faff8b68 100644 --- a/src/macro-core/macro-action-http.hpp +++ b/src/macro-core/macro-action-http.hpp @@ -3,9 +3,11 @@ #include "variable-text-edit.hpp" #include "variable-line-edit.hpp" #include "duration-control.hpp" +#include "string-list.hpp" #include #include +#include class MacroActionHttp : public MacroAction { public: @@ -30,10 +32,13 @@ public: obs_module_text("AdvSceneSwitcher.enterURL"); VariableResolvingString _data = obs_module_text("AdvSceneSwitcher.enterText"); + bool _setHeaders = false; + StringList _headers; Method _method = Method::GET; - Duration _timeout; + Duration _timeout = Duration(1.0); private: + void SetupHeaders(); void Get(); void Post(); @@ -62,6 +67,8 @@ private slots: void URLChanged(); void MethodChanged(int); void TimeoutChanged(double seconds); + void SetHeadersChanged(int); + void HeadersChanged(const StringList &); signals: void HeaderInfoChanged(const QString &); @@ -74,6 +81,9 @@ private: VariableLineEdit *_url; QComboBox *_methods; VariableTextEdit *_data; + QCheckBox *_setHeaders; + QVBoxLayout *_headerListLayout; + StringListEdit *_headerList; DurationSelection *_timeout; bool _loading = true; }; diff --git a/src/utils/curl-helper.cpp b/src/utils/curl-helper.cpp index 452e4e9b..b884231a 100644 --- a/src/utils/curl-helper.cpp +++ b/src/utils/curl-helper.cpp @@ -32,6 +32,14 @@ Curlhelper::~Curlhelper() } } +curl_slist *Curlhelper::SlistAppend(curl_slist *list, const char *string) +{ + if (!_initialized) { + return nullptr; + } + return _slistAppend(list, string); +} + CURLcode Curlhelper::Perform() { if (!_initialized) { @@ -88,10 +96,11 @@ bool Curlhelper::Resolve() { _init = (initFunction)_lib->resolve("curl_easy_init"); _setopt = (setOptFunction)_lib->resolve("curl_easy_setopt"); + _slistAppend = (slistAppendFunction)_lib->resolve("curl_slist_append"); _perform = (performFunction)_lib->resolve("curl_easy_perform"); _cleanup = (cleanupFunction)_lib->resolve("curl_easy_cleanup"); - if (_init && _setopt && _perform && _cleanup) { + if (_init && _setopt && _slistAppend && _perform && _cleanup) { blog(LOG_INFO, "[adv-ss] curl loaded successfully"); return true; } diff --git a/src/utils/curl-helper.hpp b/src/utils/curl-helper.hpp index 4cd4ea1e..e7db3821 100644 --- a/src/utils/curl-helper.hpp +++ b/src/utils/curl-helper.hpp @@ -5,6 +5,8 @@ typedef CURL *(*initFunction)(void); typedef void (*cleanupFunction)(CURL *); typedef CURLcode (*setOptFunction)(CURL *, CURLoption, ...); +typedef struct curl_slist *(*slistAppendFunction)(struct curl_slist *list, + const char *string); typedef CURLcode (*performFunction)(CURL *); class Curlhelper { @@ -13,6 +15,8 @@ public: ~Curlhelper(); template CURLcode SetOpt(CURLoption, Args...); + struct curl_slist *SlistAppend(struct curl_slist *list, + const char *string); CURLcode Perform(); bool Initialized() { return _initialized; } @@ -22,6 +26,7 @@ private: initFunction _init = nullptr; setOptFunction _setopt = nullptr; + slistAppendFunction _slistAppend = nullptr; performFunction _perform = nullptr; cleanupFunction _cleanup = nullptr; CURL *_curl = nullptr;