fgerlits commented on code in PR #1383:
URL: https://github.com/apache/nifi-minifi-cpp/pull/1383#discussion_r954631146
##########
extensions/http-curl/tests/unit/InvokeHTTPTests.cpp:
##########
@@ -433,4 +414,76 @@ TEST_CASE("InvokeHTTP Attributes to Send uses full string
matching, not substrin
REQUIRE(LogTestController::getInstance().contains("key:header
value:value2"));
REQUIRE_FALSE(LogTestController::getInstance().contains("key:invalid", 0s));
}
+
+TEST_CASE("HTTPTestsResponseBodyinAttribute", "[InvokeHTTP]") {
+ using minifi::processors::InvokeHTTP;
+
+ auto invoke_http = std::make_shared<InvokeHTTP>("InvokeHTTP");
+ test::SingleProcessorTestController test_controller{invoke_http};
+
+ minifi::extensions::curl::testing::ConnectionCountingServer
connection_counting_server;
+
+ invoke_http->setProperty(InvokeHTTP::Method, "POST");
+ invoke_http->setProperty(InvokeHTTP::URL, "http://localhost:" +
connection_counting_server.getPort() + "/reverse");
+ invoke_http->setProperty(InvokeHTTP::PutResponseBodyInAttribute,
"http.body");
+ const auto result = test_controller.trigger("data", {{"header1", "value1"},
{"header", "value2"}});
+ auto success_flow_files = result.at(InvokeHTTP::Success);
+ CHECK(result.at(InvokeHTTP::RelFailure).empty());
+ CHECK(result.at(InvokeHTTP::RelResponse).empty());
+ CHECK(result.at(InvokeHTTP::RelNoRetry).empty());
+ CHECK(result.at(InvokeHTTP::RelRetry).empty());
+ REQUIRE(success_flow_files.size() == 1);
+ CHECK(test_controller.plan->getContent(success_flow_files[0]) == "data");
+
+ auto http_type_attribute = success_flow_files[0]->getAttribute("http.body");
+ REQUIRE(http_type_attribute);
+ CHECK(*http_type_attribute == "atad");
+}
+
+TEST_CASE("HTTPTestsResponseBody", "[InvokeHTTP]") {
+ using minifi::processors::InvokeHTTP;
+
+ auto invoke_http = std::make_shared<InvokeHTTP>("InvokeHTTP");
+ test::SingleProcessorTestController test_controller{invoke_http};
+
+ minifi::extensions::curl::testing::ConnectionCountingServer
connection_counting_server;
+
+ invoke_http->setProperty(InvokeHTTP::Method, "POST");
+ invoke_http->setProperty(InvokeHTTP::URL, "http://localhost:" +
connection_counting_server.getPort() + "/reverse");
+ invoke_http->setProperty(InvokeHTTP::SendBody, "true");
Review Comment:
`SendBody` is deprecated, and it is ignored by the processor. Should this
be `SendMessageBody`?
##########
extensions/http-curl/processors/InvokeHTTP.cpp:
##########
@@ -83,165 +84,188 @@ const core::Property InvokeHTTP::ProxyUsername(
core::PropertyBuilder::createProperty("invokehttp-proxy-username", "Proxy
Username")->withDescription("Username to set when authenticating against
proxy")->isRequired(false)->build());
const core::Property InvokeHTTP::ProxyPassword(
core::PropertyBuilder::createProperty("invokehttp-proxy-password", "Proxy
Password")->withDescription("Password to set when authenticating against
proxy")->isRequired(false)->build());
-const core::Property InvokeHTTP::ContentType("Content-type", "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",
- "application/octet-stream");
+const core::Property InvokeHTTP::ContentType("Content-type",
+ "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",
+ "application/octet-stream");
const core::Property InvokeHTTP::SendBody(
core::PropertyBuilder::createProperty("send-message-body", "Send Body")
- ->withDescription("DEPRECATED. Only kept for backwards compatibility, no
functionality is included.")
- ->withDefaultValue<bool>(true)
- ->build());
+ ->withDescription("DEPRECATED. Only kept for backwards compatibility,
no functionality is included.")
+ ->withDefaultValue<bool>(true)
+ ->build());
const core::Property InvokeHTTP::SendMessageBody(
core::PropertyBuilder::createProperty("Send Message Body")
- ->withDescription("If true, sends the HTTP message body on
POST/PUT/PATCH requests (default). "
- "If false, suppresses the message body and
content-type header for these requests.")
- ->withDefaultValue<bool>(true)
- ->build());
-const core::Property InvokeHTTP::UseChunkedEncoding("Use Chunked Encoding",
"When POST'ing, PUT'ing or PATCH'ing content set this property to true in order
to not pass the 'Content-length' header"
- " and instead send
'Transfer-Encoding' with a value of 'chunked'. This will enable the data
transfer mechanism which was introduced in HTTP 1.1 "
- "to pass data of unknown lengths
in chunks.",
- "false");
-const core::Property InvokeHTTP::PropPutOutputAttributes("Put Response Body in
Attribute", "If set, the response body received back will be put into an
attribute of the original "
- "FlowFile instead of a
separate FlowFile. The attribute key to put to is determined by evaluating
value of this property. ",
- "");
-const core::Property InvokeHTTP::AlwaysOutputResponse("Always Output
Response", "Will force a response FlowFile to be generated and routed to the
'Response' relationship "
- "regardless of what the server
status code received is ",
- "false");
-const core::Property InvokeHTTP::PenalizeOnNoRetry("Penalize on \"No Retry\"",
"Enabling this property will penalize FlowFiles that are routed to the \"No
Retry\" relationship.", "false");
+ ->withDescription("If true, sends the HTTP message body on
POST/PUT/PATCH requests (default). "
+ "If false, suppresses the message body and
content-type header for these requests.")
+ ->withDefaultValue<bool>(true)
+ ->build());
+const core::Property InvokeHTTP::UseChunkedEncoding("Use Chunked Encoding",
+ "When POST'ing, PUT'ing or PATCH'ing content set this property to true in
order to not pass the 'Content-length' header"
+ " and instead send 'Transfer-Encoding' with a value of 'chunked'."
+ " This will enable the data transfer mechanism which was introduced in
HTTP 1.1 to pass data of unknown lengths in chunks.",
+ "false");
+const core::Property InvokeHTTP::PutResponseBodyInAttribute("Put Response Body
in Attribute",
+ "If set, the response body received back will be put into an attribute of
the original "
+ "FlowFile instead of a separate FlowFile. "
+ "The attribute key to put to is determined by evaluating value of this
property. ",
+ "");
+const core::Property InvokeHTTP::AlwaysOutputResponse("Always Output Response",
+ "Will force a response FlowFile to be generated and routed to the
'Response' relationship regardless of what the server status code received is ",
+ "false");
+const core::Property InvokeHTTP::PenalizeOnNoRetry("Penalize on \"No Retry\"",
+ "Enabling this property will penalize FlowFiles that are routed to the
\"No Retry\" relationship.",
+ "false");
const core::Property InvokeHTTP::DisablePeerVerification("Disable Peer
Verification", "Disables peer verification for the SSL session", "false");
const core::Property InvokeHTTP::InvalidHTTPHeaderFieldHandlingStrategy(
core::PropertyBuilder::createProperty("Invalid HTTP Header Field Handling
Strategy")
- ->withDescription("Indicates what should happen when an attribute's name
is not a valid HTTP header field name. "
- "Options: transform - invalid characters are replaced, fail - flow
file is transferred to failure, drop - drops invalid attributes from HTTP
message")
- ->isRequired(true)
-
->withDefaultValue<std::string>(toString(InvalidHTTPHeaderFieldHandlingOption::TRANSFORM))
-
->withAllowableValues<std::string>(InvalidHTTPHeaderFieldHandlingOption::values())
- ->build());
+ ->withDescription("Indicates what should happen when an attribute's
name is not a valid HTTP header field name. "
+ "Options: transform - invalid characters are
replaced, fail - flow file is transferred to failure, drop - drops invalid
attributes from HTTP message")
+ ->isRequired(true)
+
->withDefaultValue<std::string>(toString(InvalidHTTPHeaderFieldHandlingOption::TRANSFORM))
+
->withAllowableValues<std::string>(InvalidHTTPHeaderFieldHandlingOption::values())
+ ->build());
-const core::Relationship InvokeHTTP::Success("success", "The original FlowFile
will be routed upon success (2xx status codes). "
- "It will have new attributes detailing
the success of the request.");
+const core::Relationship InvokeHTTP::Success("success",
+ "The original FlowFile will be routed upon success (2xx status codes). It
will have new attributes detailing the success of the request.");
-const core::Relationship InvokeHTTP::RelResponse("response", "A Response
FlowFile will be routed upon success (2xx status codes). "
- "If the 'Always Output Response'
property is true then the response will be sent "
- "to this relationship regardless of
the status code received.");
+const core::Relationship InvokeHTTP::RelResponse("response",
+ "A Response FlowFile will be routed upon success (2xx status codes). "
+ "If the 'Always Output Response' property is true then the response will
be sent "
+ "to this relationship regardless of the status code received.");
-const core::Relationship InvokeHTTP::RelRetry("retry", "The original FlowFile
will be routed on any status code that can be retried "
- "(5xx status codes). It will have new
attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelRetry("retry",
+ "The original FlowFile will be routed on any status code that can be
retried "
+ "(5xx status codes). It will have new attributes detailing the request.");
-const core::Relationship InvokeHTTP::RelNoRetry("no retry", "The original
FlowFile will be routed on any status code that should NOT "
- "be retried (1xx, 3xx, 4xx status
codes). It will have new attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelNoRetry("no retry",
+ "The original FlowFile will be routed on any status code that should NOT "
+ "be retried (1xx, 3xx, 4xx status codes). It will have new attributes
detailing the request.");
-const core::Relationship InvokeHTTP::RelFailure("failure", "The original
FlowFile will be routed on any type of connection failure, "
- "timeout or general exception. It
will have new attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelFailure("failure",
+ "The original FlowFile will be routed on any type of connection failure, "
+ "timeout or general exception. It will have new attributes detailing the
request.");
void InvokeHTTP::initialize() {
logger_->log_trace("Initializing InvokeHTTP");
setSupportedProperties(properties());
setSupportedRelationships(relationships());
}
-void InvokeHTTP::onSchedule(const std::shared_ptr<core::ProcessContext>
&context, const std::shared_ptr<core::ProcessSessionFactory>&
/*sessionFactory*/) {
- if (!context->getProperty(Method.getName(), method_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", Method.getName(), Method.getValue());
- return;
- }
+namespace {
+void setupClientTimeouts(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto connection_timeout =
context.getProperty<core::TimePeriodValue>(InvokeHTTP::ConnectTimeout))
+ client.setConnectionTimeout(connection_timeout->getMilliseconds());
- if (!context->getProperty(URL.getName(), url_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", URL.getName(), URL.getValue());
- return;
- }
+ if (auto read_timeout =
context.getProperty<core::TimePeriodValue>(InvokeHTTP::ReadTimeout))
+ client.setReadTimeout(read_timeout->getMilliseconds());
+}
- if (auto connect_timeout =
context->getProperty<core::TimePeriodValue>(ConnectTimeout)) {
- connect_timeout_ms_ = connect_timeout->getMilliseconds();
- } else {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", ConnectTimeout.getName(), ConnectTimeout.getValue());
- return;
+void setupClientProxy(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ utils::HTTPProxy proxy = {};
+ context.getProperty(InvokeHTTP::ProxyHost.getName(), proxy.host);
+ std::string port_str;
+ if (context.getProperty(InvokeHTTP::ProxyPort.getName(), port_str) &&
!port_str.empty()) {
+ core::Property::StringToInt(port_str, proxy.port);
}
+ context.getProperty(InvokeHTTP::ProxyUsername.getName(), proxy.username);
+ context.getProperty(InvokeHTTP::ProxyPassword.getName(), proxy.password);
- std::string content_type_str;
- if (context->getProperty(ContentType.getName(), content_type_str)) {
- content_type_ = content_type_str;
- }
+ client.setHTTPProxy(proxy);
+}
- if (auto read_timeout =
context->getProperty<core::TimePeriodValue>(ReadTimeout)) {
- read_timeout_ms_ = read_timeout->getMilliseconds();
- } else {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", ReadTimeout.getName(), ReadTimeout.getValue());
- }
+void setupClientPeerVerification(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto disable_peer_verification =
context.getProperty<bool>(InvokeHTTP::DisablePeerVerification))
+ client.setPeerVerification(*disable_peer_verification);
+}
+
+void setupClientFollowRedirects(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto follow_redirects =
context.getProperty<bool>(InvokeHTTP::FollowRedirects))
+ client.setFollowRedirects(*follow_redirects);
+}
- std::string date_header_str;
- if (!context->getProperty(DateHeader.getName(), date_header_str)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", DateHeader.getName(), DateHeader.getValue());
+void setupClientContentType(extensions::curl::HTTPClient& client, const
core::ProcessContext& context, bool send_body) {
+ if (auto content_type = context.getProperty(InvokeHTTP::ContentType)) {
+ if (send_body)
+ client.setContentType(*content_type);
}
+}
- date_header_include_ =
utils::StringUtils::toBool(date_header_str).value_or(DateHeader.getValue());
+void setupClientTransferEncoding(extensions::curl::HTTPClient& client, bool
use_chunked_encoding) {
+ if (use_chunked_encoding)
+ client.setRequestHeader("Transfer-Encoding", "chunked");
Review Comment:
This is probably not a new bug, but the `DateHeader` and
`UseChunkedEncoding` properties are never read.
I'm surprised clang-tidy doesn't catch this in CI, because the clang-tidy
plugin in my IDE flags this line as unreachable code.
##########
extensions/http-curl/processors/InvokeHTTP.cpp:
##########
@@ -83,165 +84,188 @@ const core::Property InvokeHTTP::ProxyUsername(
core::PropertyBuilder::createProperty("invokehttp-proxy-username", "Proxy
Username")->withDescription("Username to set when authenticating against
proxy")->isRequired(false)->build());
const core::Property InvokeHTTP::ProxyPassword(
core::PropertyBuilder::createProperty("invokehttp-proxy-password", "Proxy
Password")->withDescription("Password to set when authenticating against
proxy")->isRequired(false)->build());
-const core::Property InvokeHTTP::ContentType("Content-type", "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",
- "application/octet-stream");
+const core::Property InvokeHTTP::ContentType("Content-type",
+ "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",
+ "application/octet-stream");
const core::Property InvokeHTTP::SendBody(
core::PropertyBuilder::createProperty("send-message-body", "Send Body")
- ->withDescription("DEPRECATED. Only kept for backwards compatibility, no
functionality is included.")
- ->withDefaultValue<bool>(true)
- ->build());
+ ->withDescription("DEPRECATED. Only kept for backwards compatibility,
no functionality is included.")
+ ->withDefaultValue<bool>(true)
+ ->build());
const core::Property InvokeHTTP::SendMessageBody(
core::PropertyBuilder::createProperty("Send Message Body")
- ->withDescription("If true, sends the HTTP message body on
POST/PUT/PATCH requests (default). "
- "If false, suppresses the message body and
content-type header for these requests.")
- ->withDefaultValue<bool>(true)
- ->build());
-const core::Property InvokeHTTP::UseChunkedEncoding("Use Chunked Encoding",
"When POST'ing, PUT'ing or PATCH'ing content set this property to true in order
to not pass the 'Content-length' header"
- " and instead send
'Transfer-Encoding' with a value of 'chunked'. This will enable the data
transfer mechanism which was introduced in HTTP 1.1 "
- "to pass data of unknown lengths
in chunks.",
- "false");
-const core::Property InvokeHTTP::PropPutOutputAttributes("Put Response Body in
Attribute", "If set, the response body received back will be put into an
attribute of the original "
- "FlowFile instead of a
separate FlowFile. The attribute key to put to is determined by evaluating
value of this property. ",
- "");
-const core::Property InvokeHTTP::AlwaysOutputResponse("Always Output
Response", "Will force a response FlowFile to be generated and routed to the
'Response' relationship "
- "regardless of what the server
status code received is ",
- "false");
-const core::Property InvokeHTTP::PenalizeOnNoRetry("Penalize on \"No Retry\"",
"Enabling this property will penalize FlowFiles that are routed to the \"No
Retry\" relationship.", "false");
+ ->withDescription("If true, sends the HTTP message body on
POST/PUT/PATCH requests (default). "
+ "If false, suppresses the message body and
content-type header for these requests.")
+ ->withDefaultValue<bool>(true)
+ ->build());
+const core::Property InvokeHTTP::UseChunkedEncoding("Use Chunked Encoding",
+ "When POST'ing, PUT'ing or PATCH'ing content set this property to true in
order to not pass the 'Content-length' header"
+ " and instead send 'Transfer-Encoding' with a value of 'chunked'."
+ " This will enable the data transfer mechanism which was introduced in
HTTP 1.1 to pass data of unknown lengths in chunks.",
+ "false");
+const core::Property InvokeHTTP::PutResponseBodyInAttribute("Put Response Body
in Attribute",
+ "If set, the response body received back will be put into an attribute of
the original "
+ "FlowFile instead of a separate FlowFile. "
+ "The attribute key to put to is determined by evaluating value of this
property. ",
+ "");
+const core::Property InvokeHTTP::AlwaysOutputResponse("Always Output Response",
+ "Will force a response FlowFile to be generated and routed to the
'Response' relationship regardless of what the server status code received is ",
+ "false");
+const core::Property InvokeHTTP::PenalizeOnNoRetry("Penalize on \"No Retry\"",
+ "Enabling this property will penalize FlowFiles that are routed to the
\"No Retry\" relationship.",
+ "false");
const core::Property InvokeHTTP::DisablePeerVerification("Disable Peer
Verification", "Disables peer verification for the SSL session", "false");
const core::Property InvokeHTTP::InvalidHTTPHeaderFieldHandlingStrategy(
core::PropertyBuilder::createProperty("Invalid HTTP Header Field Handling
Strategy")
- ->withDescription("Indicates what should happen when an attribute's name
is not a valid HTTP header field name. "
- "Options: transform - invalid characters are replaced, fail - flow
file is transferred to failure, drop - drops invalid attributes from HTTP
message")
- ->isRequired(true)
-
->withDefaultValue<std::string>(toString(InvalidHTTPHeaderFieldHandlingOption::TRANSFORM))
-
->withAllowableValues<std::string>(InvalidHTTPHeaderFieldHandlingOption::values())
- ->build());
+ ->withDescription("Indicates what should happen when an attribute's
name is not a valid HTTP header field name. "
+ "Options: transform - invalid characters are
replaced, fail - flow file is transferred to failure, drop - drops invalid
attributes from HTTP message")
+ ->isRequired(true)
+
->withDefaultValue<std::string>(toString(InvalidHTTPHeaderFieldHandlingOption::TRANSFORM))
+
->withAllowableValues<std::string>(InvalidHTTPHeaderFieldHandlingOption::values())
+ ->build());
-const core::Relationship InvokeHTTP::Success("success", "The original FlowFile
will be routed upon success (2xx status codes). "
- "It will have new attributes detailing
the success of the request.");
+const core::Relationship InvokeHTTP::Success("success",
+ "The original FlowFile will be routed upon success (2xx status codes). It
will have new attributes detailing the success of the request.");
-const core::Relationship InvokeHTTP::RelResponse("response", "A Response
FlowFile will be routed upon success (2xx status codes). "
- "If the 'Always Output Response'
property is true then the response will be sent "
- "to this relationship regardless of
the status code received.");
+const core::Relationship InvokeHTTP::RelResponse("response",
+ "A Response FlowFile will be routed upon success (2xx status codes). "
+ "If the 'Always Output Response' property is true then the response will
be sent "
+ "to this relationship regardless of the status code received.");
-const core::Relationship InvokeHTTP::RelRetry("retry", "The original FlowFile
will be routed on any status code that can be retried "
- "(5xx status codes). It will have new
attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelRetry("retry",
+ "The original FlowFile will be routed on any status code that can be
retried "
+ "(5xx status codes). It will have new attributes detailing the request.");
-const core::Relationship InvokeHTTP::RelNoRetry("no retry", "The original
FlowFile will be routed on any status code that should NOT "
- "be retried (1xx, 3xx, 4xx status
codes). It will have new attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelNoRetry("no retry",
+ "The original FlowFile will be routed on any status code that should NOT "
+ "be retried (1xx, 3xx, 4xx status codes). It will have new attributes
detailing the request.");
-const core::Relationship InvokeHTTP::RelFailure("failure", "The original
FlowFile will be routed on any type of connection failure, "
- "timeout or general exception. It
will have new attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelFailure("failure",
+ "The original FlowFile will be routed on any type of connection failure, "
+ "timeout or general exception. It will have new attributes detailing the
request.");
void InvokeHTTP::initialize() {
logger_->log_trace("Initializing InvokeHTTP");
setSupportedProperties(properties());
setSupportedRelationships(relationships());
}
-void InvokeHTTP::onSchedule(const std::shared_ptr<core::ProcessContext>
&context, const std::shared_ptr<core::ProcessSessionFactory>&
/*sessionFactory*/) {
- if (!context->getProperty(Method.getName(), method_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", Method.getName(), Method.getValue());
- return;
- }
+namespace {
+void setupClientTimeouts(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto connection_timeout =
context.getProperty<core::TimePeriodValue>(InvokeHTTP::ConnectTimeout))
+ client.setConnectionTimeout(connection_timeout->getMilliseconds());
- if (!context->getProperty(URL.getName(), url_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", URL.getName(), URL.getValue());
- return;
- }
+ if (auto read_timeout =
context.getProperty<core::TimePeriodValue>(InvokeHTTP::ReadTimeout))
+ client.setReadTimeout(read_timeout->getMilliseconds());
+}
- if (auto connect_timeout =
context->getProperty<core::TimePeriodValue>(ConnectTimeout)) {
- connect_timeout_ms_ = connect_timeout->getMilliseconds();
- } else {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", ConnectTimeout.getName(), ConnectTimeout.getValue());
- return;
+void setupClientProxy(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ utils::HTTPProxy proxy = {};
+ context.getProperty(InvokeHTTP::ProxyHost.getName(), proxy.host);
+ std::string port_str;
+ if (context.getProperty(InvokeHTTP::ProxyPort.getName(), port_str) &&
!port_str.empty()) {
+ core::Property::StringToInt(port_str, proxy.port);
}
+ context.getProperty(InvokeHTTP::ProxyUsername.getName(), proxy.username);
+ context.getProperty(InvokeHTTP::ProxyPassword.getName(), proxy.password);
- std::string content_type_str;
- if (context->getProperty(ContentType.getName(), content_type_str)) {
- content_type_ = content_type_str;
- }
+ client.setHTTPProxy(proxy);
+}
- if (auto read_timeout =
context->getProperty<core::TimePeriodValue>(ReadTimeout)) {
- read_timeout_ms_ = read_timeout->getMilliseconds();
- } else {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", ReadTimeout.getName(), ReadTimeout.getValue());
- }
+void setupClientPeerVerification(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto disable_peer_verification =
context.getProperty<bool>(InvokeHTTP::DisablePeerVerification))
+ client.setPeerVerification(*disable_peer_verification);
+}
+
+void setupClientFollowRedirects(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto follow_redirects =
context.getProperty<bool>(InvokeHTTP::FollowRedirects))
+ client.setFollowRedirects(*follow_redirects);
+}
- std::string date_header_str;
- if (!context->getProperty(DateHeader.getName(), date_header_str)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", DateHeader.getName(), DateHeader.getValue());
+void setupClientContentType(extensions::curl::HTTPClient& client, const
core::ProcessContext& context, bool send_body) {
+ if (auto content_type = context.getProperty(InvokeHTTP::ContentType)) {
+ if (send_body)
+ client.setContentType(*content_type);
}
+}
- date_header_include_ =
utils::StringUtils::toBool(date_header_str).value_or(DateHeader.getValue());
+void setupClientTransferEncoding(extensions::curl::HTTPClient& client, bool
use_chunked_encoding) {
+ if (use_chunked_encoding)
+ client.setRequestHeader("Transfer-Encoding", "chunked");
+ else
+ client.setRequestHeader("Transfer-Encoding", std::nullopt);
+}
+} // namespace
- if (!context->getProperty(PropPutOutputAttributes.getName(),
put_attribute_name_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", PropPutOutputAttributes.getName(),
PropPutOutputAttributes.getValue());
- }
+void InvokeHTTP::setupMembersFromProperties(const core::ProcessContext&
context) {
+ context.getProperty(SendMessageBody.getName(), send_body_);
- attributes_to_send_ = context->getProperty(AttributesToSend)
- | utils::filter([](const std::string& s) { return !s.empty(); }) //
avoid compiling an empty string to regex
- | utils::map([](const std::string& regex_str) { return
utils::Regex{regex_str}; })
- | utils::orElse([this] { logger_->log_debug("%s is missing, so the
default value will be used", AttributesToSend.getName()); });
+ attributes_to_send_ = context.getProperty(AttributesToSend)
+ | utils::filter([](const std::string& s) { return
!s.empty(); }) // avoid compiling an empty string to regex
+ | utils::map([](const std::string& regex_str) { return
utils::Regex{regex_str}; })
+ | utils::orElse([this] { logger_->log_debug("%s is
missing, so the default value will be used", AttributesToSend.getName()); });
- std::string always_output_response;
- if (!context->getProperty(AlwaysOutputResponse.getName(),
always_output_response)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", AlwaysOutputResponse.getName(), AlwaysOutputResponse.getValue());
- }
- always_output_response_ =
utils::StringUtils::toBool(always_output_response).value_or(false);
+ always_output_response_ =
context.getProperty<bool>(AlwaysOutputResponse).value_or(false);
+ penalize_no_retry_ =
context.getProperty<bool>(PenalizeOnNoRetry).value_or(false);
- std::string penalize_no_retry = "false";
- if (!context->getProperty(PenalizeOnNoRetry.getName(), penalize_no_retry)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", PenalizeOnNoRetry.getName(), PenalizeOnNoRetry.getValue());
- }
+ invalid_http_header_field_handling_strategy_ =
utils::parseEnumProperty<InvalidHTTPHeaderFieldHandlingOption>(context,
InvalidHTTPHeaderFieldHandlingStrategy);
- penalize_no_retry_ =
utils::StringUtils::toBool(penalize_no_retry).value_or(false);
+ put_response_body_in_attribute_ =
context.getProperty(PutResponseBodyInAttribute);
+ if (put_response_body_in_attribute_ &&
put_response_body_in_attribute_->empty()) {
+ logger_->log_warn("%s is set to an empty string",
PutResponseBodyInAttribute.getName());
+ put_response_body_in_attribute_.reset();
+ }
+}
- std::string context_name;
- if (context->getProperty(SSLContext.getName(), context_name) &&
!IsNullOrEmpty(context_name)) {
- std::shared_ptr<core::controller::ControllerService> service =
context->getControllerService(context_name);
- if (!service) {
- logger_->log_error("Couldn't find controller service with name '%s'",
context_name);
+std::unique_ptr<minifi::extensions::curl::HTTPClient>
InvokeHTTP::createHTTPClientFromPropertiesAndMembers(const
core::ProcessContext& context) const {
+ std::string method;
+ if (!context.getProperty(Method.getName(), method))
+ throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Method property missing or
invalid");
+
+ std::string url;
+ if (!context.getProperty(URL.getName(), url))
+ throw Exception(PROCESS_SCHEDULE_EXCEPTION, "URL property missing or
invalid");
+
+ std::shared_ptr<minifi::controllers::SSLContextService> ssl_context_service;
+ if (auto ssl_context_name = context.getProperty(SSLContext)) {
+ if (auto service = context.getControllerService(*ssl_context_name)) {
+ ssl_context_service =
std::dynamic_pointer_cast<minifi::controllers::SSLContextService>(service);
+ if (!ssl_context_service)
+ logger_->log_error("Controller service '%s' is not an
SSLContextService", *ssl_context_name);
} else {
- ssl_context_service_ =
std::dynamic_pointer_cast<minifi::controllers::SSLContextService>(service);
- if (!ssl_context_service_) {
- logger_->log_error("Controller service '%s' is not an
SSLContextService", context_name);
- }
+ logger_->log_error("Couldn't find controller service with name '%s'",
*ssl_context_name);
}
}
- std::string use_chunked_encoding = "false";
- if (!context->getProperty(UseChunkedEncoding.getName(),
use_chunked_encoding)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", UseChunkedEncoding.getName(), UseChunkedEncoding.getValue());
- }
+ auto client = std::make_unique<minifi::extensions::curl::HTTPClient>();
+ client->initialize(std::move(method), std::move(url),
std::move(ssl_context_service));
+ setupClientTimeouts(*client, context);
+ setupClientProxy(*client, context);
+ setupClientFollowRedirects(*client, context);
+ setupClientPeerVerification(*client, context);
+ setupClientContentType(*client, context, send_body_);
+ setupClientTransferEncoding(*client, use_chunked_encoding_);
- use_chunked_encoding_ =
utils::StringUtils::toBool(use_chunked_encoding).value_or(false);
+ return client;
+}
- std::string disable_peer_verification;
- disable_peer_verification_ =
(context->getProperty(DisablePeerVerification.getName(),
disable_peer_verification) &&
utils::StringUtils::toBool(disable_peer_verification).value_or(false));
- proxy_ = {};
- context->getProperty(ProxyHost.getName(), proxy_.host);
- std::string port_str;
- if (context->getProperty(ProxyPort.getName(), port_str) &&
!port_str.empty()) {
- core::Property::StringToInt(port_str, proxy_.port);
- }
- context->getProperty(ProxyUsername.getName(), proxy_.username);
- context->getProperty(ProxyPassword.getName(), proxy_.password);
- context->getProperty(FollowRedirects.getName(), follow_redirects_);
- context->getProperty(SendMessageBody.getName(), send_body_);
+void InvokeHTTP::onSchedule(const std::shared_ptr<core::ProcessContext>&
context, const std::shared_ptr<core::ProcessSessionFactory>&
/*sessionFactory*/) {
+ gsl_Expects(context);
- invalid_http_header_field_handling_strategy_ =
utils::parseEnumProperty<InvalidHTTPHeaderFieldHandlingOption>(*context,
InvalidHTTPHeaderFieldHandlingStrategy);
+ setupMembersFromProperties(*context);
+ client_queue_ =
gsl::make_not_null(utils::ResourceQueue<extensions::curl::HTTPClient>::create(getMaxConcurrentTasks(),
logger_));
}
-bool InvokeHTTP::shouldEmitFlowFile() const {
- return ("POST" == method_ || "PUT" == method_ || "PATCH" == method_);
+bool InvokeHTTP::shouldEmitFlowFile(minifi::extensions::curl::HTTPClient&
client) {
Review Comment:
why is this function no longer const?
##########
extensions/http-curl/processors/InvokeHTTP.cpp:
##########
@@ -83,165 +84,188 @@ const core::Property InvokeHTTP::ProxyUsername(
core::PropertyBuilder::createProperty("invokehttp-proxy-username", "Proxy
Username")->withDescription("Username to set when authenticating against
proxy")->isRequired(false)->build());
const core::Property InvokeHTTP::ProxyPassword(
core::PropertyBuilder::createProperty("invokehttp-proxy-password", "Proxy
Password")->withDescription("Password to set when authenticating against
proxy")->isRequired(false)->build());
-const core::Property InvokeHTTP::ContentType("Content-type", "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",
- "application/octet-stream");
+const core::Property InvokeHTTP::ContentType("Content-type",
+ "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",
+ "application/octet-stream");
const core::Property InvokeHTTP::SendBody(
core::PropertyBuilder::createProperty("send-message-body", "Send Body")
- ->withDescription("DEPRECATED. Only kept for backwards compatibility, no
functionality is included.")
- ->withDefaultValue<bool>(true)
- ->build());
+ ->withDescription("DEPRECATED. Only kept for backwards compatibility,
no functionality is included.")
+ ->withDefaultValue<bool>(true)
+ ->build());
const core::Property InvokeHTTP::SendMessageBody(
core::PropertyBuilder::createProperty("Send Message Body")
- ->withDescription("If true, sends the HTTP message body on
POST/PUT/PATCH requests (default). "
- "If false, suppresses the message body and
content-type header for these requests.")
- ->withDefaultValue<bool>(true)
- ->build());
-const core::Property InvokeHTTP::UseChunkedEncoding("Use Chunked Encoding",
"When POST'ing, PUT'ing or PATCH'ing content set this property to true in order
to not pass the 'Content-length' header"
- " and instead send
'Transfer-Encoding' with a value of 'chunked'. This will enable the data
transfer mechanism which was introduced in HTTP 1.1 "
- "to pass data of unknown lengths
in chunks.",
- "false");
-const core::Property InvokeHTTP::PropPutOutputAttributes("Put Response Body in
Attribute", "If set, the response body received back will be put into an
attribute of the original "
- "FlowFile instead of a
separate FlowFile. The attribute key to put to is determined by evaluating
value of this property. ",
- "");
-const core::Property InvokeHTTP::AlwaysOutputResponse("Always Output
Response", "Will force a response FlowFile to be generated and routed to the
'Response' relationship "
- "regardless of what the server
status code received is ",
- "false");
-const core::Property InvokeHTTP::PenalizeOnNoRetry("Penalize on \"No Retry\"",
"Enabling this property will penalize FlowFiles that are routed to the \"No
Retry\" relationship.", "false");
+ ->withDescription("If true, sends the HTTP message body on
POST/PUT/PATCH requests (default). "
+ "If false, suppresses the message body and
content-type header for these requests.")
+ ->withDefaultValue<bool>(true)
+ ->build());
+const core::Property InvokeHTTP::UseChunkedEncoding("Use Chunked Encoding",
+ "When POST'ing, PUT'ing or PATCH'ing content set this property to true in
order to not pass the 'Content-length' header"
+ " and instead send 'Transfer-Encoding' with a value of 'chunked'."
+ " This will enable the data transfer mechanism which was introduced in
HTTP 1.1 to pass data of unknown lengths in chunks.",
+ "false");
+const core::Property InvokeHTTP::PutResponseBodyInAttribute("Put Response Body
in Attribute",
+ "If set, the response body received back will be put into an attribute of
the original "
+ "FlowFile instead of a separate FlowFile. "
+ "The attribute key to put to is determined by evaluating value of this
property. ",
+ "");
+const core::Property InvokeHTTP::AlwaysOutputResponse("Always Output Response",
+ "Will force a response FlowFile to be generated and routed to the
'Response' relationship regardless of what the server status code received is ",
+ "false");
+const core::Property InvokeHTTP::PenalizeOnNoRetry("Penalize on \"No Retry\"",
+ "Enabling this property will penalize FlowFiles that are routed to the
\"No Retry\" relationship.",
+ "false");
const core::Property InvokeHTTP::DisablePeerVerification("Disable Peer
Verification", "Disables peer verification for the SSL session", "false");
const core::Property InvokeHTTP::InvalidHTTPHeaderFieldHandlingStrategy(
core::PropertyBuilder::createProperty("Invalid HTTP Header Field Handling
Strategy")
- ->withDescription("Indicates what should happen when an attribute's name
is not a valid HTTP header field name. "
- "Options: transform - invalid characters are replaced, fail - flow
file is transferred to failure, drop - drops invalid attributes from HTTP
message")
- ->isRequired(true)
-
->withDefaultValue<std::string>(toString(InvalidHTTPHeaderFieldHandlingOption::TRANSFORM))
-
->withAllowableValues<std::string>(InvalidHTTPHeaderFieldHandlingOption::values())
- ->build());
+ ->withDescription("Indicates what should happen when an attribute's
name is not a valid HTTP header field name. "
+ "Options: transform - invalid characters are
replaced, fail - flow file is transferred to failure, drop - drops invalid
attributes from HTTP message")
+ ->isRequired(true)
+
->withDefaultValue<std::string>(toString(InvalidHTTPHeaderFieldHandlingOption::TRANSFORM))
+
->withAllowableValues<std::string>(InvalidHTTPHeaderFieldHandlingOption::values())
+ ->build());
-const core::Relationship InvokeHTTP::Success("success", "The original FlowFile
will be routed upon success (2xx status codes). "
- "It will have new attributes detailing
the success of the request.");
+const core::Relationship InvokeHTTP::Success("success",
+ "The original FlowFile will be routed upon success (2xx status codes). It
will have new attributes detailing the success of the request.");
-const core::Relationship InvokeHTTP::RelResponse("response", "A Response
FlowFile will be routed upon success (2xx status codes). "
- "If the 'Always Output Response'
property is true then the response will be sent "
- "to this relationship regardless of
the status code received.");
+const core::Relationship InvokeHTTP::RelResponse("response",
+ "A Response FlowFile will be routed upon success (2xx status codes). "
+ "If the 'Always Output Response' property is true then the response will
be sent "
+ "to this relationship regardless of the status code received.");
-const core::Relationship InvokeHTTP::RelRetry("retry", "The original FlowFile
will be routed on any status code that can be retried "
- "(5xx status codes). It will have new
attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelRetry("retry",
+ "The original FlowFile will be routed on any status code that can be
retried "
+ "(5xx status codes). It will have new attributes detailing the request.");
-const core::Relationship InvokeHTTP::RelNoRetry("no retry", "The original
FlowFile will be routed on any status code that should NOT "
- "be retried (1xx, 3xx, 4xx status
codes). It will have new attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelNoRetry("no retry",
+ "The original FlowFile will be routed on any status code that should NOT "
+ "be retried (1xx, 3xx, 4xx status codes). It will have new attributes
detailing the request.");
-const core::Relationship InvokeHTTP::RelFailure("failure", "The original
FlowFile will be routed on any type of connection failure, "
- "timeout or general exception. It
will have new attributes detailing the request.");
+const core::Relationship InvokeHTTP::RelFailure("failure",
+ "The original FlowFile will be routed on any type of connection failure, "
+ "timeout or general exception. It will have new attributes detailing the
request.");
void InvokeHTTP::initialize() {
logger_->log_trace("Initializing InvokeHTTP");
setSupportedProperties(properties());
setSupportedRelationships(relationships());
}
-void InvokeHTTP::onSchedule(const std::shared_ptr<core::ProcessContext>
&context, const std::shared_ptr<core::ProcessSessionFactory>&
/*sessionFactory*/) {
- if (!context->getProperty(Method.getName(), method_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", Method.getName(), Method.getValue());
- return;
- }
+namespace {
+void setupClientTimeouts(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto connection_timeout =
context.getProperty<core::TimePeriodValue>(InvokeHTTP::ConnectTimeout))
+ client.setConnectionTimeout(connection_timeout->getMilliseconds());
- if (!context->getProperty(URL.getName(), url_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", URL.getName(), URL.getValue());
- return;
- }
+ if (auto read_timeout =
context.getProperty<core::TimePeriodValue>(InvokeHTTP::ReadTimeout))
+ client.setReadTimeout(read_timeout->getMilliseconds());
+}
- if (auto connect_timeout =
context->getProperty<core::TimePeriodValue>(ConnectTimeout)) {
- connect_timeout_ms_ = connect_timeout->getMilliseconds();
- } else {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", ConnectTimeout.getName(), ConnectTimeout.getValue());
- return;
+void setupClientProxy(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ utils::HTTPProxy proxy = {};
+ context.getProperty(InvokeHTTP::ProxyHost.getName(), proxy.host);
+ std::string port_str;
+ if (context.getProperty(InvokeHTTP::ProxyPort.getName(), port_str) &&
!port_str.empty()) {
+ core::Property::StringToInt(port_str, proxy.port);
}
+ context.getProperty(InvokeHTTP::ProxyUsername.getName(), proxy.username);
+ context.getProperty(InvokeHTTP::ProxyPassword.getName(), proxy.password);
- std::string content_type_str;
- if (context->getProperty(ContentType.getName(), content_type_str)) {
- content_type_ = content_type_str;
- }
+ client.setHTTPProxy(proxy);
+}
- if (auto read_timeout =
context->getProperty<core::TimePeriodValue>(ReadTimeout)) {
- read_timeout_ms_ = read_timeout->getMilliseconds();
- } else {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", ReadTimeout.getName(), ReadTimeout.getValue());
- }
+void setupClientPeerVerification(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto disable_peer_verification =
context.getProperty<bool>(InvokeHTTP::DisablePeerVerification))
+ client.setPeerVerification(*disable_peer_verification);
+}
+
+void setupClientFollowRedirects(extensions::curl::HTTPClient& client, const
core::ProcessContext& context) {
+ if (auto follow_redirects =
context.getProperty<bool>(InvokeHTTP::FollowRedirects))
+ client.setFollowRedirects(*follow_redirects);
+}
- std::string date_header_str;
- if (!context->getProperty(DateHeader.getName(), date_header_str)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", DateHeader.getName(), DateHeader.getValue());
+void setupClientContentType(extensions::curl::HTTPClient& client, const
core::ProcessContext& context, bool send_body) {
+ if (auto content_type = context.getProperty(InvokeHTTP::ContentType)) {
+ if (send_body)
+ client.setContentType(*content_type);
}
+}
- date_header_include_ =
utils::StringUtils::toBool(date_header_str).value_or(DateHeader.getValue());
+void setupClientTransferEncoding(extensions::curl::HTTPClient& client, bool
use_chunked_encoding) {
+ if (use_chunked_encoding)
+ client.setRequestHeader("Transfer-Encoding", "chunked");
+ else
+ client.setRequestHeader("Transfer-Encoding", std::nullopt);
+}
+} // namespace
- if (!context->getProperty(PropPutOutputAttributes.getName(),
put_attribute_name_)) {
- logger_->log_debug("%s attribute is missing, so default value of %s will
be used", PropPutOutputAttributes.getName(),
PropPutOutputAttributes.getValue());
- }
+void InvokeHTTP::setupMembersFromProperties(const core::ProcessContext&
context) {
+ context.getProperty(SendMessageBody.getName(), send_body_);
Review Comment:
I would rename `send_body_` to `send_message_body_`, as there is also a
(non-functional) `SendBody` property, which makes this confusing.
##########
extensions/http-curl/processors/InvokeHTTP.h:
##########
@@ -127,52 +130,37 @@ class InvokeHTTP : public core::Processor {
EXTENSIONAPI static constexpr const char* STATUS_CODE =
"invokehttp.status.code";
EXTENSIONAPI static constexpr const char* STATUS_MESSAGE =
"invokehttp.status.message";
- EXTENSIONAPI static constexpr const char* RESPONSE_BODY =
"invokehttp.response.body";
EXTENSIONAPI static constexpr const char* REQUEST_URL =
"invokehttp.request.url";
EXTENSIONAPI static constexpr const char* TRANSACTION_ID =
"invokehttp.tx.id";
- EXTENSIONAPI static constexpr const char* REMOTE_DN = "invokehttp.remote.dn";
- EXTENSIONAPI static constexpr const char* EXCEPTION_CLASS =
"invokehttp.java.exception.class";
- EXTENSIONAPI static constexpr const char* EXCEPTION_MESSAGE =
"invokehttp.java.exception.message";
- void onTrigger(const std::shared_ptr<core::ProcessContext> &context, const
std::shared_ptr<core::ProcessSession> &session) override;
+ void onTrigger(const std::shared_ptr<core::ProcessContext>& context, const
std::shared_ptr<core::ProcessSession>& session) override;
void initialize() override;
- void onSchedule(const std::shared_ptr<core::ProcessContext> &context, const
std::shared_ptr<core::ProcessSessionFactory> &sessionFactory) override;
+ void onSchedule(const std::shared_ptr<core::ProcessContext>& context, const
std::shared_ptr<core::ProcessSessionFactory>& sessionFactory) override;
private:
- /**
- * Routes the flowfile to the proper destination
- * @param request request flow file record
- * @param response response flow file record
- * @param session process session
- * @param context process context
- * @param isSuccess success code or not
- * @param statuscode http response code.
- */
- void route(const std::shared_ptr<core::FlowFile> &request, const
std::shared_ptr<core::FlowFile> &response, const
std::shared_ptr<core::ProcessSession> &session,
- const std::shared_ptr<core::ProcessContext> &context, bool
is_success, int64_t status_code);
- bool shouldEmitFlowFile() const;
+ void route(const std::shared_ptr<core::FlowFile>& request, const
std::shared_ptr<core::FlowFile>& response, const
std::shared_ptr<core::ProcessSession>& session,
+ const std::shared_ptr<core::ProcessContext>& context, bool
is_success, int64_t status_code);
+ static bool shouldEmitFlowFile(minifi::extensions::curl::HTTPClient& client);
+ void onTriggerWithClient(const std::shared_ptr<core::ProcessContext>&
context, const std::shared_ptr<core::ProcessSession>& session,
minifi::extensions::curl::HTTPClient& client);
[[nodiscard]] bool appendHeaders(const core::FlowFile& flow_file,
/*std::invocable<std::string, std::string>*/ auto append_header);
- std::shared_ptr<minifi::controllers::SSLContextService> ssl_context_service_;
- std::string method_;
- std::string url_;
- bool date_header_include_{true};
+
+ void setupMembersFromProperties(const core::ProcessContext& context);
+ std::unique_ptr<minifi::extensions::curl::HTTPClient>
createHTTPClientFromPropertiesAndMembers(const core::ProcessContext& context)
const;
+
std::optional<utils::Regex> attributes_to_send_;
- std::chrono::milliseconds connect_timeout_ms_{20000};
- std::chrono::milliseconds read_timeout_ms_{20000};
- // attribute in which response body will be added
- std::string put_attribute_name_;
+
+ std::optional<std::string> put_response_body_in_attribute_;
bool always_output_response_{false};
- std::string content_type_;
bool use_chunked_encoding_{false};
bool penalize_no_retry_{false};
- // disabling peer verification makes susceptible for MITM attacks
- bool disable_peer_verification_{false};
- utils::HTTPProxy proxy_;
- bool follow_redirects_{true};
bool send_body_{true};
+
InvalidHTTPHeaderFieldHandlingOption
invalid_http_header_field_handling_strategy_;
+
std::shared_ptr<core::logging::Logger>
logger_{core::logging::LoggerFactory<InvokeHTTP>::getLogger()};
+
gsl::not_null<std::shared_ptr<utils::ResourceQueue<extensions::curl::HTTPClient>>>
client_queue_ = gsl::make_not_null(
+
utils::ResourceQueue<extensions::curl::HTTPClient>::create(getMaxConcurrentTasks(),
logger_));
Review Comment:
has `max_concurrent_tasks_` been already set when this runs?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]