From 2c71ac9be0f8b88e207f4f32cca6a13cc5b59efd Mon Sep 17 00:00:00 2001 From: Marcos Bento Date: Fri, 18 Oct 2024 14:01:28 +0100 Subject: [PATCH] Enable HTTPS on the Client side Re ECFLOW-1957 --- Viewer/ecflowUI/src/ServerAddDialog.ui | 17 ++++++++++ Viewer/ecflowUI/src/ServerEditDialog.ui | 17 ++++++++++ Viewer/ecflowUI/src/ServerHandler.cpp | 34 ++++++++++++++++--- Viewer/ecflowUI/src/ServerHandler.hpp | 8 +++-- Viewer/ecflowUI/src/ServerItem.cpp | 31 ++++++++++++++--- Viewer/ecflowUI/src/ServerItem.hpp | 15 ++++++-- Viewer/ecflowUI/src/ServerList.cpp | 32 ++++++++++------- Viewer/ecflowUI/src/ServerList.hpp | 4 ++- Viewer/ecflowUI/src/ServerListDialog.cpp | 25 ++++++++++++-- Viewer/ecflowUI/src/ServerListDialog.hpp | 9 +++-- Viewer/ecflowUI/src/SessionHandler.cpp | 2 +- libs/base/src/ecflow/base/HttpClient.cpp | 25 +++++++++++--- libs/base/src/ecflow/base/HttpClient.hpp | 8 ++++- .../src/ecflow/client/ClientEnvironment.hpp | 16 ++++++--- .../src/ecflow/client/ClientInvoker.cpp | 14 ++++---- .../src/ecflow/client/ClientInvoker.hpp | 2 +- .../src/ecflow/client/ClientOptions.cpp | 8 +++++ libs/pyext/src/ecflow/python/ExportClient.cpp | 2 +- 18 files changed, 218 insertions(+), 51 deletions(-) diff --git a/Viewer/ecflowUI/src/ServerAddDialog.ui b/Viewer/ecflowUI/src/ServerAddDialog.ui index 486c48bbe..1a83d7097 100644 --- a/Viewer/ecflowUI/src/ServerAddDialog.ui +++ b/Viewer/ecflowUI/src/ServerAddDialog.ui @@ -118,7 +118,24 @@ + + + + Use &HTTPS: + + + httpsCb + + + + + + + + + + diff --git a/Viewer/ecflowUI/src/ServerEditDialog.ui b/Viewer/ecflowUI/src/ServerEditDialog.ui index c5dfdac88..d409d86e2 100644 --- a/Viewer/ecflowUI/src/ServerEditDialog.ui +++ b/Viewer/ecflowUI/src/ServerEditDialog.ui @@ -122,7 +122,24 @@ + + + + Use &HTTPS: + + + httpsCh + + + + + + + + + + diff --git a/Viewer/ecflowUI/src/ServerHandler.cpp b/Viewer/ecflowUI/src/ServerHandler.cpp index 8b4d7619d..c6c2e740b 100644 --- a/Viewer/ecflowUI/src/ServerHandler.cpp +++ b/Viewer/ecflowUI/src/ServerHandler.cpp @@ -57,13 +57,15 @@ ServerHandler::ServerHandler(const std::string& name, const std::string& port, const std::string& user, bool ssl, - bool http) + bool http, + bool https) : name_(name), host_(host), port_(port), user_(user), ssl_(ssl), http_(http), + https_(https), client_(nullptr), updating_(false), communicating_(false), @@ -186,7 +188,7 @@ void ServerHandler::createClient(bool init) { bool ssl_enabled = false; std::string ssl_error; - bool http_enabled = false; +// bool http_enabled = false; std::string http_error; if (client_) { @@ -210,7 +212,17 @@ void ServerHandler::createClient(bool init) { if (http_) { try { client_->enable_http(); - http_enabled = true; +// http_enabled = true; + } + catch (std::exception& e) { + http_error = std::string(e.what()); + } + } + + if (https_) { + try { + client_->enable_https(); +// http_enabled = true; } catch (std::exception& e) { http_error = std::string(e.what()); @@ -339,6 +351,17 @@ void ServerHandler::setHttp(bool http) { } } +void ServerHandler::setHttps(bool https) { + if (https != https_) { + https_ = https; + + if (connectState_->state() != ConnectState::VersionIncompatible && + connectState_->state() != ConnectState::FailedClient) { + recreateClient(); + } + } +} + void ServerHandler::setUser(const std::string& user) { if (user != user_) { user_ = user; @@ -553,8 +576,9 @@ ServerHandler* ServerHandler::addServer(const std::string& name, const std::string& port, const std::string& user, bool ssl, - bool http) { - auto* sh = new ServerHandler(name, host, port, user, ssl, http); + bool http, + bool https) { + auto* sh = new ServerHandler(name, host, port, user, ssl, http, https); return sh; } diff --git a/Viewer/ecflowUI/src/ServerHandler.hpp b/Viewer/ecflowUI/src/ServerHandler.hpp index 7cc521724..b2129daf4 100644 --- a/Viewer/ecflowUI/src/ServerHandler.hpp +++ b/Viewer/ecflowUI/src/ServerHandler.hpp @@ -63,6 +63,7 @@ class ServerHandler : public QObject { const std::string& user() { return user_; } void setSsl(bool); void setHttp(bool); + void setHttps(bool); void setUser(const std::string& user); Activity activity() const { return activity_; } @@ -121,7 +122,8 @@ class ServerHandler : public QObject { const std::string& port, const std::string& user, bool ssl, - bool http); + bool http, + bool https); static void removeServer(ServerHandler*); static ServerHandler* findServer(const std::string& alias); @@ -146,7 +148,8 @@ class ServerHandler : public QObject { const std::string& port, const std::string& user, bool ssl, - bool http); + bool http, + bool https); ~ServerHandler() override; void logoutAndDelete(); void queueLoggedOut(); @@ -172,6 +175,7 @@ class ServerHandler : public QObject { std::string user_; bool ssl_; bool http_; + bool https_; ClientInvoker* client_; std::string longName_; std::string fullLongName_; diff --git a/Viewer/ecflowUI/src/ServerItem.cpp b/Viewer/ecflowUI/src/ServerItem.cpp index ee4ec19c8..fc642a1c4 100644 --- a/Viewer/ecflowUI/src/ServerItem.cpp +++ b/Viewer/ecflowUI/src/ServerItem.cpp @@ -27,14 +27,16 @@ ServerItem::ServerItem(const std::string& name, const std::string& user, bool favourite, bool ssl, - bool http) + bool http, + bool https) : name_(name), host_(host), port_(port), user_(user), favourite_(favourite), ssl_(ssl), - http_(http) { + http_(http), + https_(https) { } ServerItem::~ServerItem() { @@ -52,7 +54,9 @@ void ServerItem::reset(const std::string& name, const std::string& host, const std::string& port, const std::string& user, - bool ssl) { + bool ssl, + bool http, + bool https) { if (name_ != name) { name_ = name; if (handler_) { @@ -60,12 +64,20 @@ void ServerItem::reset(const std::string& name, } } - if (host == host_ && port == port_) { + if (host == host_ && port == port_ && ssl) { // TODO: these should be called together setSsl(ssl); setUser(user); } + else if (host == host_ && port == port_ && http) { + setHttp(http); + } + + else if (host == host_ && port == port_ && https) { + setHttps(https); + } + // host or port changed: full reload needed and this situation cannot // be handled here! else { @@ -105,6 +117,15 @@ void ServerItem::setHttp(bool b) { // broadcastChanged(); } +void ServerItem::setHttps(bool b) { + if (https_ != b) { + https_ = b; + if (handler_) + handler_->setHttps(https_); + } + // broadcastChanged(); +} + void ServerItem::setUser(const std::string& user) { if (user_ != user) { user_ = user; @@ -125,7 +146,7 @@ std::string ServerItem::longName() const { void ServerItem::registerUsageBegin() { if (!handler_) { - handler_ = ServerHandler::addServer(name_, host_, port_, user_, ssl_, http_); + handler_ = ServerHandler::addServer(name_, host_, port_, user_, ssl_, http_, https_); } if (handler_) useCnt_++; diff --git a/Viewer/ecflowUI/src/ServerItem.hpp b/Viewer/ecflowUI/src/ServerItem.hpp index a41b6ad46..8f650fadb 100644 --- a/Viewer/ecflowUI/src/ServerItem.hpp +++ b/Viewer/ecflowUI/src/ServerItem.hpp @@ -42,6 +42,7 @@ class ServerItem { bool isSystem() const { return system_; } bool isSsl() const { return ssl_; } bool isHttp() const { return http_; } + bool isHttps() const { return https_; } bool isUsed() const; int useCnt() const { return useCnt_; } @@ -58,18 +59,25 @@ class ServerItem { const std::string& user, bool favourite, bool ssl, - bool http); + bool http, + bool https); ~ServerItem(); void name(const std::string& name) { name_ = name; } void host(const std::string& host) { host_ = host; } void port(const std::string& port) { port_ = port; } - void - reset(const std::string& name, const std::string& host, const std::string& port, const std::string& user, bool ssl); + void reset(const std::string& name, + const std::string& host, + const std::string& port, + const std::string& user, + bool ssl, + bool http, + bool https); void setFavourite(bool b); void setSystem(bool b); void setSsl(bool b); void setHttp(bool b); + void setHttps(bool b); void setUser(const std::string&); void registerUsageBegin(); @@ -86,6 +94,7 @@ class ServerItem { bool system_{false}; bool ssl_{false}; bool http_{false}; + bool https_{false}; int useCnt_{0}; ServerHandler* handler_{nullptr}; diff --git a/Viewer/ecflowUI/src/ServerList.cpp b/Viewer/ecflowUI/src/ServerList.cpp index 5dfce1808..86a393bdb 100644 --- a/Viewer/ecflowUI/src/ServerList.cpp +++ b/Viewer/ecflowUI/src/ServerList.cpp @@ -368,6 +368,7 @@ ServerItem* ServerList::add(const std::string& name, bool favourite, bool ssl, bool http, + bool https, bool saveIt) { std::string errStr; if (!checkItemToAdd(name, host, port, true, errStr)) { @@ -375,7 +376,7 @@ ServerItem* ServerList::add(const std::string& name, return nullptr; } - auto* item = new ServerItem(name, host, port, user, favourite, ssl, http); + auto* item = new ServerItem(name, host, port, user, favourite, ssl, http, https); items_.push_back(item); @@ -405,7 +406,8 @@ ServerItem* ServerList::reset(ServerItem* item, const std::string& port, const std::string& user, bool ssl, - bool http) { + bool http, + bool https) { auto it = std::find(items_.begin(), items_.end(), item); if (it != items_.end()) { // Check if there is an item with the same name. Names have to be unique! @@ -416,14 +418,14 @@ ServerItem* ServerList::reset(ServerItem* item, items_.erase(it); broadcastChanged(); delete item; - item = add(name, host, port, user, false, ssl, http, true); + item = add(name, host, port, user, false, ssl, http, https, true); save(); broadcastChanged(); } else { assert(host == item->host()); assert(port == item->port()); - item->reset(name, host, port, user, ssl); + item->reset(name, host, port, user, ssl, http, https); save(); broadcastChanged(); } @@ -563,11 +565,16 @@ bool ServerList::load() { http = (sv[7] == "1") ? true : false; } + bool https = false; + if (sv.size() >= 9) { + https = (sv[8] == "1") ? true : false; + } + if (sv.size() >= 3) { std::string name = sv[0], host = sv[1], port = sv[2]; ServerItem* item = nullptr; try { - item = add(name, host, port, user, favourite, ssl, http, false); + item = add(name, host, port, user, favourite, ssl, http, https, false); UI_ASSERT(item != nullptr, "name=" << name << " host=" << host << " port=" << port << " user=" << user); item->setSystem(sys); } @@ -606,15 +613,16 @@ void ServerList::save() { if (!out.good()) return; - out << "#Name Host Port Favourite System Ssl user Http" << std::endl; + out << "#Name Host Port Favourite System Ssl user Http Https" << std::endl; for (auto& item : items_) { - std::string fav = (item->isFavourite()) ? "1" : "0"; - std::string ssl = (item->isSsl()) ? "1" : "0"; + std::string fav = (item->isFavourite()) ? "1" : "0"; + std::string ssl = (item->isSsl()) ? "1" : "0"; std::string http = (item->isHttp()) ? "1" : "0"; - std::string sys = (item->isSystem()) ? "1" : "0"; + std::string https = (item->isHttps()) ? "1" : "0"; + std::string sys = (item->isSystem()) ? "1" : "0"; out << item->name() << "," << item->host() << "," << item->port() << "," << fav << "," << sys << "," << ssl - << "," << item->user() << "," << http << std::endl; + << "," << item->user() << "," << http << "," << https << std::endl; } out.close(); } @@ -670,7 +678,7 @@ void ServerList::loadSystemItems(const std::vector& sysVec, changed = true; std::string name = sysItem.name(), host = sysItem.host(), port = sysItem.port(); try { - item = add(name, host, port, "", false, false, false, false); + item = add(name, host, port, "", false, false, false, false, false); UI_ASSERT(item != nullptr, "name=" << name << " host=" << host << " port=" << port); item->setSystem(true); changeVec.push_back( @@ -696,7 +704,7 @@ void ServerList::loadSystemItems(const std::vector& sysVec, ServerListTmpItem localTmp(item); changeVec.push_back(new ServerListSyncChangeItem(sysItem, localTmp, ServerListSyncChangeItem::MatchChange)); - item = reset(item, sysItem.name(), sysItem.host(), sysItem.port(), "", false, false); + item = reset(item, sysItem.name(), sysItem.host(), sysItem.port(), "", false, false, false); if (item) { item->setSystem(true); } diff --git a/Viewer/ecflowUI/src/ServerList.hpp b/Viewer/ecflowUI/src/ServerList.hpp index 4a87c2dd7..fdfbbf16a 100644 --- a/Viewer/ecflowUI/src/ServerList.hpp +++ b/Viewer/ecflowUI/src/ServerList.hpp @@ -133,6 +133,7 @@ class ServerList { bool favorite, bool ssl, bool http, + bool https, bool saveIt); void remove(ServerItem*); ServerItem* reset(ServerItem*, @@ -141,7 +142,8 @@ class ServerList { const std::string& port, const std::string& user, bool ssl, - bool http); + bool http, + bool https); void setFavourite(ServerItem*, bool); std::string uniqueName(const std::string&); diff --git a/Viewer/ecflowUI/src/ServerListDialog.cpp b/Viewer/ecflowUI/src/ServerListDialog.cpp index fe6cdddd3..9b66d778c 100644 --- a/Viewer/ecflowUI/src/ServerListDialog.cpp +++ b/Viewer/ecflowUI/src/ServerListDialog.cpp @@ -206,6 +206,10 @@ bool ServerAddDialog::isHttp() const { return httpCb->isChecked(); } +bool ServerAddDialog::isHttps() const { + return httpsCb->isChecked(); +} + bool ServerAddDialog::addToView() const { return addToCurrentCb->isChecked(); } @@ -223,6 +227,7 @@ ServerEditDialog::ServerEditDialog(QString name, bool favourite, bool ssl, bool http, + bool https, QWidget* parent) : QDialog(parent), ServerDialogChecker(tr("Cannot modify server!")), @@ -236,6 +241,7 @@ ServerEditDialog::ServerEditDialog(QString name, favCh->setChecked(favourite); sslCh->setChecked(ssl); httpCh->setChecked(http); + httpsCh->setChecked(https); #ifndef ECF_OPENSSL sslMessageLabel->hide(); @@ -300,6 +306,10 @@ bool ServerEditDialog::isHttp() const { return httpCh->isChecked(); } +bool ServerEditDialog::isHttps() const { + return httpsCh->isChecked(); +} + //====================================== // // ServerListDialog @@ -449,6 +459,7 @@ void ServerListDialog::editItem(const QModelIndex& index) { item->isFavourite(), item->isSsl(), item->isHttp(), + item->isHttps(), this); // The dialog checks the name, host and port! @@ -462,7 +473,8 @@ void ServerListDialog::editItem(const QModelIndex& index) { d.port().toStdString(), d.user().toStdString(), d.isSsl(), - d.isHttp()); + d.isHttp(), + d.isHttps()); if (item) { if (item->isFavourite() != d.isFavourite()) { @@ -490,6 +502,7 @@ void ServerListDialog::duplicateItem(const QModelIndex& index) { item->isFavourite(), item->isSsl(), item->isHttp(), + item->isHttps(), this); // The dialog checks the name, host and port! @@ -502,6 +515,7 @@ void ServerListDialog::duplicateItem(const QModelIndex& index) { item->isFavourite(), item->isSsl(), item->isHttp(), + item->isHttps(), false); model_->dataChangeFinished(); } @@ -523,6 +537,7 @@ void ServerListDialog::addItem() { false, d.isSsl(), d.isHttp(), + d.isHttps(), false); } catch (std::exception& e) { @@ -787,7 +802,7 @@ void ServerListModel::dataChangeFinished() { } int ServerListModel::columnCount(const QModelIndex& /*parent*/) const { - return 9; + return std::underlying_type::type(ServerListModel::UseColumn); } int ServerListModel::rowCount(const QModelIndex& parent) const { @@ -823,6 +838,8 @@ QVariant ServerListModel::data(const QModelIndex& index, int role) const { return (item->isSsl()) ? "ssl" : ""; case HttpColumn: return (item->isHttp()) ? "http" : ""; + case HttpsColumn: + return (item->isHttps()) ? "https" : ""; case UseColumn: { int n = item->useCnt(); if (n > 0) @@ -911,6 +928,8 @@ QVariant ServerListModel::headerData(int section, Qt::Orientation ori, int role) return tr("SSL"); case HttpColumn: return tr("HTTP"); + case HttpsColumn: + return tr("HTTPS"); case FavouriteColumn: return tr("F"); case UseColumn: @@ -939,6 +958,8 @@ QVariant ServerListModel::headerData(int section, Qt::Orientation ori, int role) return tr("Indicates if a server uses SSL communication."); case HttpColumn: return tr("Indicates if a server uses HTTP communication."); + case HttpsColumn: + return tr("Indicates if a server uses HTTPS communication."); case FavouriteColumn: return tr("Indicates if a server is a favourite. Only favourite and loaded servers \ are appearing in the server list under the Servers menu in the menubar"); diff --git a/Viewer/ecflowUI/src/ServerListDialog.hpp b/Viewer/ecflowUI/src/ServerListDialog.hpp index e54ad66b1..6a40dcf9b 100644 --- a/Viewer/ecflowUI/src/ServerListDialog.hpp +++ b/Viewer/ecflowUI/src/ServerListDialog.hpp @@ -47,6 +47,7 @@ class ServerEditDialog : public QDialog, private Ui::ServerEditDialog, public Se bool favourite, bool ssl, bool http, + bool https, QWidget* parent = nullptr); QString name() const; @@ -55,6 +56,7 @@ class ServerEditDialog : public QDialog, private Ui::ServerEditDialog, public Se QString user() const; bool isSsl() const; bool isHttp() const; + bool isHttps() const; bool isFavourite() const; public Q_SLOTS: @@ -77,6 +79,7 @@ class ServerAddDialog : public QDialog, private Ui::ServerAddDialog, public Serv bool addToView() const; bool isSsl() const; bool isHttp() const; + bool isHttps() const; public Q_SLOTS: void accept() override; @@ -161,8 +164,10 @@ class ServerListModel : public QAbstractItemModel { SystemColumn = 5, SslColumn = 6, HttpColumn = 7, - FavouriteColumn = 8, - UseColumn = 9 + HttpsColumn = 8, + FavouriteColumn = 9, + UseColumn = 10 + // when updating the columns list, ensure to update the columnCount() method to refer to last enum entry }; enum CustomItemRole { IconStatusRole = Qt::UserRole + 1 }; diff --git a/Viewer/ecflowUI/src/SessionHandler.cpp b/Viewer/ecflowUI/src/SessionHandler.cpp index 69c243791..ca52c4e31 100644 --- a/Viewer/ecflowUI/src/SessionHandler.cpp +++ b/Viewer/ecflowUI/src/SessionHandler.cpp @@ -282,7 +282,7 @@ void SessionHandler::setTemporarySessionIfReqested() { if (ServerList::instance()->find(alias, host, port) == nullptr) { // no - add it, and make sure it's got a unique alias std::string uniqueName = ServerList::instance()->uniqueName(alias); - ServerList::instance()->add(uniqueName, host, port, "", false, false, false, true); + ServerList::instance()->add(uniqueName, host, port, "", false, false, false, false, true); } } } diff --git a/libs/base/src/ecflow/base/HttpClient.cpp b/libs/base/src/ecflow/base/HttpClient.cpp index 8eae03af4..7e7be8003 100644 --- a/libs/base/src/ecflow/base/HttpClient.cpp +++ b/libs/base/src/ecflow/base/HttpClient.cpp @@ -17,13 +17,30 @@ #include "ecflow/base/stc/StcCmd.hpp" #include "ecflow/core/Converter.hpp" -HttpClient::HttpClient(Cmd_ptr cmd_ptr, const std::string& host, const std::string& port, int timeout) - : host_(host), +static std::string make_scheme_host_port(const std::string& scheme, const std::string& host, const std::string& port) { + return scheme + "://" + host + ":" + port; +}; + +HttpClient::HttpClient(Cmd_ptr cmd_ptr, + const std::string& scheme, + const std::string& host, + const std::string& port, + int timeout) + : scheme_(scheme), + host_(host), port_(port), - client_(host, ecf::convert_to(port)) { + base_url_(make_scheme_host_port(scheme, host, port)), + client_(base_url_) { + + std::cout << " >>> Client configured to connect to: " << base_url_ << std::endl; client_.set_connection_timeout(std::chrono::seconds{timeout}); + // Disable cert verification + if (scheme_ == "https") { + client_.enable_server_certificate_verification(false); + } + if (!cmd_ptr.get()) { throw std::runtime_error("Client::Client: No request specified !"); } @@ -38,7 +55,7 @@ void HttpClient::run() { auto result = client_.Post("/v1/ecflow", outbound, "application/json"); if (result) { auto response = result.value(); - status_ = httplib::Error::Success; + status_ = httplib::Error::Success; ecf::restore_from_string(response.body, inbound_response_); } else { diff --git a/libs/base/src/ecflow/base/HttpClient.hpp b/libs/base/src/ecflow/base/HttpClient.hpp index 58bf9226d..0e3f698a3 100644 --- a/libs/base/src/ecflow/base/HttpClient.hpp +++ b/libs/base/src/ecflow/base/HttpClient.hpp @@ -28,7 +28,11 @@ class HttpClient { public: /// Constructor starts the asynchronous connect operation. - HttpClient(Cmd_ptr cmd_ptr, const std::string& host, const std::string& port, int timout = 60); + HttpClient(Cmd_ptr cmd_ptr, + const std::string& scheme, + const std::string& host, + const std::string& port, + int timeout = 60); void run(); @@ -38,8 +42,10 @@ class HttpClient { bool handle_server_response(ServerReply&, bool debug) const; private: + std::string scheme_; /// the scheme to use std::string host_; /// the servers name std::string port_; /// the port on the server + std::string base_url_; httplib::Client client_; httplib::Response response_; diff --git a/libs/client/src/ecflow/client/ClientEnvironment.hpp b/libs/client/src/ecflow/client/ClientEnvironment.hpp index a4597361e..1945686a8 100644 --- a/libs/client/src/ecflow/client/ClientEnvironment.hpp +++ b/libs/client/src/ecflow/client/ClientEnvironment.hpp @@ -91,8 +91,15 @@ class ClientEnvironment final : public AbstractClientEnv { void set_debug(bool flag); bool http() const { return http_; } - void enable_http() { http_ = true; } - void disable_http() { http_ = false; } + void enable_http() { + http_ = true; + scheme_ = "http"; + } + void enable_https() { + http_ = true; + scheme_ = "https"; + } + std::string scheme() const { return scheme_; } #ifdef ECF_OPENSSL /// return true if this is a ssl enabled server @@ -100,11 +107,11 @@ class ClientEnvironment final : public AbstractClientEnv { bool ssl() const { return ssl_.enabled(); } void enable_ssl_if_defined() { ssl_.enable_if_defined(host(), port()); - } // IF ECF_SSL=1,search server.crt, ELSE search ..crt + } // IF ECF_SSL=1,search server.crt, ELSE search ..crt void enable_ssl() { ssl_.enable(host(), port()); } // search server.crt first, then ..crt bool enable_ssl_no_throw() { return ssl_.enable_no_throw(host(), port()); - } // search server.crt first, then ..crt + } // search server.crt first, then ..crt void disable_ssl() { ssl_.disable(); } // override environment setting for ECF_SSL #endif @@ -173,6 +180,7 @@ class ClientEnvironment final : public AbstractClientEnv { // immediately bool no_ecf_{false}; // NO_ECF. if defined then abort cmd immediately. useful when test jobs stand-alone bool http_{false}; + std::string scheme_{"http"}; // default is https bool debug_{false}; // For live debug, enabled by env variable ECF_CLIENT_DEBUG or set by option -d|--debug bool under_test_{false}; // Used in testing client interface bool host_file_read_{false}; // to ensure we read host file only once diff --git a/libs/client/src/ecflow/client/ClientInvoker.cpp b/libs/client/src/ecflow/client/ClientInvoker.cpp index fce556e0c..aeab174fd 100644 --- a/libs/client/src/ecflow/client/ClientInvoker.cpp +++ b/libs/client/src/ecflow/client/ClientInvoker.cpp @@ -444,12 +444,12 @@ int ClientInvoker::do_invoke_cmd(Cmd_ptr cts_cmd) const { } else #endif - if (clientEnv_.http()) { + if (clientEnv_.http()) { if (clientEnv_.debug()) { cout << TimeStamp::now() << "ClientInvoker: >>> Using HTTP client <<<" << endl; } - HttpClient theClient(cts_cmd, clientEnv_.host(), clientEnv_.port()); + HttpClient theClient(cts_cmd, clientEnv_.scheme(), clientEnv_.host(), clientEnv_.port()); theClient.run(); if (clientEnv_.debug()) { @@ -472,10 +472,10 @@ int ClientInvoker::do_invoke_cmd(Cmd_ptr cts_cmd) const { else { if (clientEnv_.debug()) { - cout << TimeStamp::now() << "ClientInvoker: >>> Using TCP/IP client (without SSL) <<<" << endl; + cout << TimeStamp::now() << "ClientInvoker: >>> Using TCP/IP client (without SSL) <<<" + << endl; } - Client theClient( io, cts_cmd, clientEnv_.host(), clientEnv_.port(), clientEnv_.connect_timeout()); { @@ -1542,7 +1542,7 @@ bool ClientInvoker::is_free_port(int port, bool debug) { const auto the_port = ecf::convert_to(port); try { if (debug) { - cout << " Trying to connect to server on '" << Str::LOCALHOST() << ":" << the_port << "'\n"; + cout << " Trying to connect to server on '" << Str::LOCALHOST() << ":" << the_port << "'\n"; } client.set_host_port(Str::LOCALHOST(), the_port); client.pingServer(); @@ -1558,7 +1558,8 @@ bool ClientInvoker::is_free_port(int port, bool debug) { } if (msg.find("authentication failed") != std::string::npos) { if (debug) { - cout << " Could not connect, due to authentication failure, hence port " << the_port << " is used. Returning FALSE\n"; + cout << " Could not connect, due to authentication failure, hence port " << the_port + << " is used. Returning FALSE\n"; } return false; } @@ -1577,7 +1578,6 @@ bool ClientInvoker::is_free_port(int port, bool debug) { return true; } - std::string ClientInvoker::find_free_port(int seed_port_number, bool debug) { // Ping failed, We need to distinguish between: // a/ Server does not exist : port diff --git a/libs/client/src/ecflow/client/ClientInvoker.hpp b/libs/client/src/ecflow/client/ClientInvoker.hpp index 6744c74df..f476d964e 100644 --- a/libs/client/src/ecflow/client/ClientInvoker.hpp +++ b/libs/client/src/ecflow/client/ClientInvoker.hpp @@ -74,7 +74,7 @@ class ClientInvoker { #endif void enable_http() { clientEnv_.enable_http(); } - void disable_http() { clientEnv_.disable_http(); } + void enable_https() { clientEnv_.enable_https(); } /// This will override the environment setting. /// In particular setting host explicitly will avoid cycling through server list, diff --git a/libs/client/src/ecflow/client/ClientOptions.cpp b/libs/client/src/ecflow/client/ClientOptions.cpp index 2dedaf97b..3bf526101 100644 --- a/libs/client/src/ecflow/client/ClientOptions.cpp +++ b/libs/client/src/ecflow/client/ClientOptions.cpp @@ -81,6 +81,9 @@ ClientOptions::ClientOptions() { desc_->add_options()( "http", "Enables communication over HTTP between client/server.\n"); + desc_->add_options()( + "https", + "Enables communication over HTTPS between client/server.\n"); // clang-format on } @@ -193,6 +196,11 @@ Cmd_ptr ClientOptions::parse(const CommandLine& cl, ClientEnvironment* env) cons std::cout << " http set via command line\n"; env->enable_http(); } + if (vm.count("https")) { + if (env->debug()) + std::cout << " https set via command line\n"; + env->enable_https(); + } // Defer the parsing of the command , to the command. This allows // all cmd functionality to be centralised with the command diff --git a/libs/pyext/src/ecflow/python/ExportClient.cpp b/libs/pyext/src/ecflow/python/ExportClient.cpp index 20f3eb162..1cc364a22 100644 --- a/libs/pyext/src/ecflow/python/ExportClient.cpp +++ b/libs/pyext/src/ecflow/python/ExportClient.cpp @@ -664,7 +664,7 @@ void export_Client() { #endif .def("enable_http", &ClientInvoker::enable_http, "Enable HTTP communication") - .def("disable_http", &ClientInvoker::disable_http, "Disable HTTP communication") + .def("enable_https", &ClientInvoker::enable_https, "Enable HTTPS communication") .def("zombie_get", &zombieGet, return_value_policy()) .def("zombie_fob", &ClientInvoker::zombieFobCli)