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);