This is an automated email from the ASF dual-hosted git repository.

szaszm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/main by this push:
     new 8479439  MINIFICPP-1359 Implement FollowRedirects property in 
InvokeHTTP
8479439 is described below

commit 8479439dab2b6753faded9952bc79d3b2b666bcf
Author: Gabor Gyimesi <[email protected]>
AuthorDate: Mon Apr 12 12:50:12 2021 +0200

    MINIFICPP-1359 Implement FollowRedirects property in InvokeHTTP
    
    Closes #1043
    
    Signed-off-by: Marton Szasz <[email protected]>
---
 PROCESSORS.md                                      |  1 +
 extensions/http-curl/client/HTTPClient.cpp         |  4 ++
 extensions/http-curl/client/HTTPClient.h           |  2 +
 extensions/http-curl/processors/InvokeHTTP.cpp     |  9 +++-
 extensions/http-curl/processors/InvokeHTTP.h       |  1 +
 extensions/http-curl/tests/HTTPHandlers.h          |  8 +++
 .../http-curl/tests/VerifyInvokeHTTPTest.cpp       | 61 ++++++++++++++++++----
 7 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/PROCESSORS.md b/PROCESSORS.md
index 0306c42..0dccd22 100644
--- a/PROCESSORS.md
+++ b/PROCESSORS.md
@@ -682,6 +682,7 @@ In the list below, the names of required properties appear 
in bold. Any other pr
 |Connection Timeout|5 secs||Max wait time for connection to remote service.|
 |Content-type|application/octet-stream||The Content-Type to specify for when 
content is being transmitted through a PUT, POST or PATCH. In the case of an 
empty value after evaluating an expression language expression, Content-Type 
defaults to|
 |Disable Peer Verification|false||Disables peer verification for the SSL 
session|
+|Follow Redirects|true||Follow HTTP redirects issued by remote server.|
 |HTTP Method|GET||HTTP request method (GET, POST, PUT, PATCH, DELETE, HEAD, 
OPTIONS). Arbitrary methods are also supported. Methods other than POST, PUT 
and PATCH will be sent without a message body.|
 |Include Date Header|true||Include an RFC-2616 Date header in the request.|
 |Proxy Host|||The fully qualified hostname or IP address of the proxy server|
diff --git a/extensions/http-curl/client/HTTPClient.cpp 
b/extensions/http-curl/client/HTTPClient.cpp
index f628b4f..9e2aceb 100644
--- a/extensions/http-curl/client/HTTPClient.cpp
+++ b/extensions/http-curl/client/HTTPClient.cpp
@@ -434,6 +434,10 @@ void HTTPClient::setInterface(const std::string &ifc) {
   curl_easy_setopt(http_session_, CURLOPT_INTERFACE, ifc.c_str());
 }
 
+void HTTPClient::setFollowRedirects(bool follow) {
+  curl_easy_setopt(http_session_, CURLOPT_FOLLOWLOCATION, follow);
+}
+
 }  // namespace utils
 }  // namespace minifi
 }  // namespace nifi
diff --git a/extensions/http-curl/client/HTTPClient.h 
b/extensions/http-curl/client/HTTPClient.h
index 6a4e8c9..ceb36f9 100644
--- a/extensions/http-curl/client/HTTPClient.h
+++ b/extensions/http-curl/client/HTTPClient.h
@@ -173,6 +173,8 @@ class HTTPClient : public BaseHTTPClient, public 
core::Connectable {
 
   void setInterface(const std::string &);
 
+  void setFollowRedirects(bool follow);
+
   const std::map<std::string, std::string> &getParsedHeaders() override {
     return header_response_.getHeaderMap();
   }
diff --git a/extensions/http-curl/processors/InvokeHTTP.cpp 
b/extensions/http-curl/processors/InvokeHTTP.cpp
index c0b2b87..d6fa2f8 100644
--- a/extensions/http-curl/processors/InvokeHTTP.cpp
+++ b/extensions/http-curl/processors/InvokeHTTP.cpp
@@ -75,7 +75,11 @@ core::Property InvokeHTTP::ReadTimeout(
 core::Property InvokeHTTP::DateHeader(
     core::PropertyBuilder::createProperty("Include Date 
Header")->withDescription("Include an RFC-2616 Date header in the 
request.")->isRequired(false)->withDefaultValue<bool>(true)->build());
 
-core::Property InvokeHTTP::FollowRedirects("Follow Redirects", "Follow HTTP 
redirects issued by remote server.", "True");
+core::Property InvokeHTTP::FollowRedirects(
+  core::PropertyBuilder::createProperty("Follow Redirects")
+  ->withDescription("Follow HTTP redirects issued by remote server.")
+  ->withDefaultValue<bool>(true)
+  ->build());
 core::Property InvokeHTTP::AttributesToSend("Attributes to Send", "Regular 
expression that defines which attributes to send as HTTP"
                                             " headers in the request. If not 
defined, no attributes are sent as headers.",
                                             "");
@@ -154,6 +158,7 @@ void InvokeHTTP::initialize() {
   properties.insert(SendBody);
   properties.insert(DisablePeerVerification);
   properties.insert(AlwaysOutputResponse);
+  properties.insert(FollowRedirects);
 
   setSupportedProperties(properties);
   // Set the supported relationships
@@ -258,6 +263,7 @@ void InvokeHTTP::onSchedule(const 
std::shared_ptr<core::ProcessContext> &context
   }
   context->getProperty(ProxyUsername.getName(), proxy_.username);
   context->getProperty(ProxyPassword.getName(), proxy_.password);
+  context->getProperty(FollowRedirects.getName(), follow_redirects_);
 }
 
 InvokeHTTP::~InvokeHTTP() = default;
@@ -303,6 +309,7 @@ void InvokeHTTP::onTrigger(const 
std::shared_ptr<core::ProcessContext> &context,
   client.initialize(method_);
   client.setConnectionTimeout(connect_timeout_ms_);
   client.setReadTimeout(read_timeout_ms_);
+  client.setFollowRedirects(follow_redirects_);
 
   if (!content_type_.empty()) {
     client.setContentType(content_type_);
diff --git a/extensions/http-curl/processors/InvokeHTTP.h 
b/extensions/http-curl/processors/InvokeHTTP.h
index cdf11e4..b56b7c5 100644
--- a/extensions/http-curl/processors/InvokeHTTP.h
+++ b/extensions/http-curl/processors/InvokeHTTP.h
@@ -158,6 +158,7 @@ class InvokeHTTP : public core::Processor {
   // disable peer verification ( makes susceptible for MITM attacks )
   bool disable_peer_verification_{false};
   utils::HTTPProxy proxy_;
+  bool follow_redirects_{true};
 
  private:
   std::shared_ptr<logging::Logger> 
logger_{logging::LoggerFactory<InvokeHTTP>::getLogger()};
diff --git a/extensions/http-curl/tests/HTTPHandlers.h 
b/extensions/http-curl/tests/HTTPHandlers.h
index 76015e4..cedb834 100644
--- a/extensions/http-curl/tests/HTTPHandlers.h
+++ b/extensions/http-curl/tests/HTTPHandlers.h
@@ -550,6 +550,14 @@ public:
   }
 };
 
+class InvokeHTTPRedirectHandler : public ServerAwareHandler {
+public:
+  bool handlePost(CivetServer *, struct mg_connection *conn) override {
+    mg_printf(conn, "HTTP/1.1 301 OK\r\nContent-Type: 
text/plain\r\nContent-Length: 0\r\nLocation: /\r\n\r\n");
+    return true;
+  }
+};
+
 class InvokeHTTPResponse404Handler : public ServerAwareHandler {
 public:
   bool handlePost(CivetServer *, struct mg_connection *conn) override {
diff --git a/extensions/http-curl/tests/VerifyInvokeHTTPTest.cpp 
b/extensions/http-curl/tests/VerifyInvokeHTTPTest.cpp
index db0830f..6fa4713 100644
--- a/extensions/http-curl/tests/VerifyInvokeHTTPTest.cpp
+++ b/extensions/http-curl/tests/VerifyInvokeHTTPTest.cpp
@@ -56,7 +56,19 @@ class VerifyInvokeHTTP : public HTTPIntegrationBase {
     proc->setProperty(minifi::processors::InvokeHTTP::URL.getName(), url);
   }
 
-  void setupFlow(const utils::optional<std::string>& flow_yml_path) {
+  void setProperty(const std::string& property, const std::string& value) {
+    const auto components = flowController_->getComponents("InvokeHTTP");
+    assert(!components.empty());
+
+    const auto stateController = components.at(0);
+    assert(stateController);
+    const auto processorController = 
std::dynamic_pointer_cast<minifi::state::ProcessorController>(stateController);
+    assert(processorController);
+    auto proc = processorController->getProcessor();
+    proc->setProperty(property, value);
+  }
+
+  virtual void setupFlow(const utils::optional<std::string>& flow_yml_path) {
     testSetup();
 
     std::shared_ptr<core::Repository> test_repo = 
std::make_shared<TestRepository>();
@@ -75,14 +87,8 @@ class VerifyInvokeHTTP : public HTTPIntegrationBase {
     flowController_ = std::make_shared<minifi::FlowController>(test_repo, 
test_flow_repo, configuration, std::move(yaml_ptr), content_repo, 
DEFAULT_ROOT_GROUP_NAME, true);
     flowController_->load();
 
-    const auto components = flowController_->getComponents("InvokeHTTP");
-    assert(!components.empty());
-
-    const auto stateController = components.at(0);
-    assert(stateController);
-    const auto processorController = 
std::dynamic_pointer_cast<minifi::state::ProcessorController>(stateController);
-    assert(processorController);
-    setProperties(processorController->getProcessor());
+    std::string url = scheme + "://localhost:" + getWebPort() + *path_;
+    setProperty(minifi::processors::InvokeHTTP::URL.getName(), url);
   }
 
   void run(const utils::optional<std::string>& flow_yml_path = {}, const 
utils::optional<std::string>& = {}) override {
@@ -120,6 +126,31 @@ class VerifyInvokeHTTPOKResponse : public VerifyInvokeHTTP 
{
   }
 };
 
+class VerifyInvokeHTTPOK200Response : public VerifyInvokeHTTP {
+ public:
+  void runAssertions() override {
+    using org::apache::nifi::minifi::utils::verifyLogLinePresenceInPollTime;
+    assert(verifyLogLinePresenceInPollTime(std::chrono::seconds(6),
+        "key:invokehttp.status.code value:200",
+        "response code 200"));
+  }
+};
+
+class VerifyInvokeHTTPRedirectResponse : public VerifyInvokeHTTP {
+ public:
+  void setupFlow(const utils::optional<std::string>& flow_yml_path) override {
+    VerifyInvokeHTTP::setupFlow(flow_yml_path);
+    setProperty(minifi::processors::InvokeHTTP::FollowRedirects.getName(), 
"false");
+  }
+
+  void runAssertions() override {
+    using org::apache::nifi::minifi::utils::verifyLogLinePresenceInPollTime;
+    assert(verifyLogLinePresenceInPollTime(std::chrono::seconds(6),
+        "key:invokehttp.status.code value:301",
+        "response code 301"));
+  }
+};
+
 class VerifyCouldNotConnectInvokeHTTP : public VerifyInvokeHTTP {
  public:
   void runAssertions() override {
@@ -193,6 +224,18 @@ int main(int argc, char ** argv) {
   }
 
   {
+    InvokeHTTPRedirectHandler handler;
+    VerifyInvokeHTTPOK200Response harness;
+    run(harness, args.url, args.test_file, args.key_dir, &handler);
+  }
+
+  {
+    InvokeHTTPRedirectHandler handler;
+    VerifyInvokeHTTPRedirectResponse harness;
+    run(harness, args.url, args.test_file, args.key_dir, &handler);
+  }
+
+  {
     InvokeHTTPResponse404Handler handler;
     VerifyNoRetryInvokeHTTP harness;
     run(harness, args.url, args.test_file, args.key_dir, &handler);

Reply via email to