This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 25643ea641 fix #5759, allow empty parameters in http client (#5762)
25643ea641 is described below
commit 25643ea641930fb7636f2bbc5e2529221d9740a3
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Thu Oct 2 15:51:44 2025 +0200
fix #5759, allow empty parameters in http client (#5762)
---
... => 0002-http-client-test-empty-parameters.hpl} | 74 ++-
.../http/0002-http-client-test-parameters.hpl | 49 +-
integration-tests/http/main-0002-http-client.hwf | 145 +++--
.../apache/hop/pipeline/transforms/http/Http.java | 17 +-
.../hop/pipeline/transforms/http/HttpData.java | 2 +-
.../hop/pipeline/transforms/http/HttpMeta.java | 282 +--------
.../hop/pipeline/transforms/http/HttpDataTest.java | 255 ++++++++
.../hop/pipeline/transforms/http/HttpMetaTest.java | 341 +++++++++++
.../hop/pipeline/transforms/http/HttpTest.java | 661 +++++++++++++++++++--
9 files changed, 1358 insertions(+), 468 deletions(-)
diff --git a/integration-tests/http/0002-http-client-test-parameters.hpl
b/integration-tests/http/0002-http-client-test-empty-parameters.hpl
similarity index 88%
copy from integration-tests/http/0002-http-client-test-parameters.hpl
copy to integration-tests/http/0002-http-client-test-empty-parameters.hpl
index 861aa5902e..181f13721c 100644
--- a/integration-tests/http/0002-http-client-test-parameters.hpl
+++ b/integration-tests/http/0002-http-client-test-empty-parameters.hpl
@@ -19,7 +19,7 @@ limitations under the License.
-->
<pipeline>
<info>
- <name>0002-http-client-test-parameters</name>
+ <name>0002-http-client-test-empty-parameters</name>
<name_sync_with_filename>Y</name_sync_with_filename>
<description/>
<extended_description/>
@@ -40,8 +40,6 @@ limitations under the License.
<created_date>2021/09/27 10:47:43.922</created_date>
<modified_user>-</modified_user>
<modified_date>2021/09/27 10:47:43.922</modified_date>
- <key_for_session_key>H4sIAAAAAAAAAAMAAAAAAAAAAAA=</key_for_session_key>
- <is_key_private>N</is_key_private>
</info>
<notepads>
</notepads>
@@ -102,16 +100,30 @@ limitations under the License.
<field>
<length>-1</length>
<name>parameter</name>
+ <nullif>parametervalue</nullif>
+ <precision>-1</precision>
+ <set_empty_string>N</set_empty_string>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <name>empty_string</name>
+ <precision>-1</precision>
+ <set_empty_string>Y</set_empty_string>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <name>null_string</name>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
<type>String</type>
- <nullif>parametervalue</nullif>
</field>
</fields>
<interval_in_ms>5000</interval_in_ms>
<last_time_field>FiveSecondsAgo</last_time_field>
- <never_ending>N</never_ending>
<limit>1</limit>
+ <never_ending>N</never_ending>
<row_time_field>now</row_time_field>
<attributes/>
<GUI>
@@ -132,6 +144,7 @@ limitations under the License.
</partitioning>
<url>http://${HOSTNAME}/get</url>
<urlInField>N</urlInField>
+ <ignoreSsl>N</ignoreSsl>
<urlField/>
<encoding>UTF-8</encoding>
<httpLogin/>
@@ -146,6 +159,14 @@ limitations under the License.
<name>parameter</name>
<parameter>parameter</parameter>
</arg>
+ <arg>
+ <name>empty_string</name>
+ <parameter>empty_parameter</parameter>
+ </arg>
+ <arg>
+ <name>null_string</name>
+ <parameter>null_parameter</parameter>
+ </arg>
</lookup>
<result>
<name>result</name>
@@ -232,44 +253,47 @@ limitations under the License.
<method>none</method>
<schema_name/>
</partitioning>
- <send_true_to/>
- <send_false_to/>
<compare>
<condition>
- <negated>N</negated>
<conditions>
<condition>
- <negated>Y</negated>
- <leftvalue>result_status</leftvalue>
+ <conditions>
+</conditions>
<function>=</function>
- <rightvalue/>
+ <leftvalue>result_status</leftvalue>
+ <negated>Y</negated>
+ <operator>-</operator>
<value>
- <name>constant</name>
- <type>Integer</type>
- <text>200</text>
- <length>-1</length>
- <precision>0</precision>
<isnull>N</isnull>
+ <length>-1</length>
<mask>#</mask>
+ <name>constant</name>
+ <precision>0</precision>
+ <text>200</text>
+ <type>Integer</type>
</value>
</condition>
<condition>
- <negated>Y</negated>
- <operator>AND</operator>
- <leftvalue>parameter_result</leftvalue>
+ <conditions>
+</conditions>
<function>=</function>
- <rightvalue/>
+ <leftvalue>parameter_result</leftvalue>
+ <negated>Y</negated>
+ <operator>OR</operator>
<value>
- <name>constant</name>
- <type>String</type>
- <text>{"parameter":"parametervalue"}</text>
- <length>-1</length>
- <precision>-1</precision>
<isnull>N</isnull>
+ <length>-1</length>
<mask/>
+ <name>constant</name>
+ <precision>-1</precision>
+
<text>{"empty_parameter":"","null_parameter":"","parameter":"parametervalue"}</text>
+ <type>String</type>
</value>
</condition>
</conditions>
+ <function>=</function>
+ <negated>N</negated>
+ <operator>-</operator>
</condition>
</compare>
<attributes/>
diff --git a/integration-tests/http/0002-http-client-test-parameters.hpl
b/integration-tests/http/0002-http-client-test-parameters.hpl
index 861aa5902e..7cada798ef 100644
--- a/integration-tests/http/0002-http-client-test-parameters.hpl
+++ b/integration-tests/http/0002-http-client-test-parameters.hpl
@@ -40,8 +40,6 @@ limitations under the License.
<created_date>2021/09/27 10:47:43.922</created_date>
<modified_user>-</modified_user>
<modified_date>2021/09/27 10:47:43.922</modified_date>
- <key_for_session_key>H4sIAAAAAAAAAAMAAAAAAAAAAAA=</key_for_session_key>
- <is_key_private>N</is_key_private>
</info>
<notepads>
</notepads>
@@ -102,16 +100,16 @@ limitations under the License.
<field>
<length>-1</length>
<name>parameter</name>
+ <nullif>parametervalue</nullif>
<precision>-1</precision>
<set_empty_string>N</set_empty_string>
<type>String</type>
- <nullif>parametervalue</nullif>
</field>
</fields>
<interval_in_ms>5000</interval_in_ms>
<last_time_field>FiveSecondsAgo</last_time_field>
- <never_ending>N</never_ending>
<limit>1</limit>
+ <never_ending>N</never_ending>
<row_time_field>now</row_time_field>
<attributes/>
<GUI>
@@ -132,6 +130,7 @@ limitations under the License.
</partitioning>
<url>http://${HOSTNAME}/get</url>
<urlInField>N</urlInField>
+ <ignoreSsl>N</ignoreSsl>
<urlField/>
<encoding>UTF-8</encoding>
<httpLogin/>
@@ -232,44 +231,46 @@ limitations under the License.
<method>none</method>
<schema_name/>
</partitioning>
- <send_true_to/>
- <send_false_to/>
<compare>
<condition>
- <negated>N</negated>
<conditions>
<condition>
- <negated>Y</negated>
- <leftvalue>result_status</leftvalue>
+ <conditions>
+</conditions>
<function>=</function>
- <rightvalue/>
+ <leftvalue>result_status</leftvalue>
+ <negated>Y</negated>
+ <operator>-</operator>
<value>
- <name>constant</name>
- <type>Integer</type>
- <text>200</text>
- <length>-1</length>
- <precision>0</precision>
<isnull>N</isnull>
+ <length>-1</length>
<mask>#</mask>
+ <name>constant</name>
+ <precision>0</precision>
+ <text>200</text>
+ <type>Integer</type>
</value>
</condition>
<condition>
- <negated>Y</negated>
- <operator>AND</operator>
- <leftvalue>parameter_result</leftvalue>
+ <conditions>
+</conditions>
<function>=</function>
- <rightvalue/>
+ <leftvalue>parameter_result</leftvalue>
+ <negated>Y</negated>
+ <operator>OR</operator>
<value>
- <name>constant</name>
- <type>String</type>
- <text>{"parameter":"parametervalue"}</text>
+ <isnull>N</isnull>
<length>-1</length>
+ <name>constant</name>
<precision>-1</precision>
- <isnull>N</isnull>
- <mask/>
+ <text>{"parameter":"parametervalue"}</text>
+ <type>String</type>
</value>
</condition>
</conditions>
+ <function>=</function>
+ <negated>N</negated>
+ <operator>-</operator>
</condition>
</compare>
<attributes/>
diff --git a/integration-tests/http/main-0002-http-client.hwf
b/integration-tests/http/main-0002-http-client.hwf
index d266f856d7..95b630c318 100644
--- a/integration-tests/http/main-0002-http-client.hwf
+++ b/integration-tests/http/main-0002-http-client.hwf
@@ -41,14 +41,15 @@ limitations under the License.
<description/>
<type>SPECIAL</type>
<attributes/>
- <repeat>N</repeat>
- <schedulerType>0</schedulerType>
- <intervalSeconds>0</intervalSeconds>
- <intervalMinutes>60</intervalMinutes>
+ <DayOfMonth>1</DayOfMonth>
+ <doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution>
<hour>12</hour>
+ <intervalMinutes>60</intervalMinutes>
+ <intervalSeconds>0</intervalSeconds>
<minutes>0</minutes>
+ <repeat>N</repeat>
+ <schedulerType>0</schedulerType>
<weekDay>1</weekDay>
- <DayOfMonth>1</DayOfMonth>
<parallel>N</parallel>
<xloc>50</xloc>
<yloc>48</yloc>
@@ -59,74 +60,56 @@ limitations under the License.
<description/>
<type>PIPELINE</type>
<attributes/>
- <filename>${PROJECT_HOME}/0002-http-client.hpl</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <clear_rows>N</clear_rows>
- <clear_files>N</clear_files>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
<add_date>N</add_date>
<add_time>N</add_time>
- <loglevel>Basic</loglevel>
- <set_append_logfile>N</set_append_logfile>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
+ <clear_files>N</clear_files>
+ <clear_rows>N</clear_rows>
<create_parent_folder>N</create_parent_folder>
- <run_configuration>local</run_configuration>
+ <exec_per_row>N</exec_per_row>
+ <filename>${PROJECT_HOME}/0002-http-client.hpl</filename>
+ <loglevel>Basic</loglevel>
<parameters>
- <pass_all_parameters>Y</pass_all_parameters>
<parameter>
<name>HOSTNAME</name>
- <stream_name/>
<value>${HOSTNAME}</value>
</parameter>
+ <pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <params_from_previous>N</params_from_previous>
+ <run_configuration>local</run_configuration>
+ <set_append_logfile>N</set_append_logfile>
+ <set_logfile>N</set_logfile>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
<xloc>310</xloc>
<yloc>48</yloc>
<attributes_hac/>
</action>
- <action>
- <name>Abort workflow</name>
- <description/>
- <type>ABORT</type>
- <attributes/>
- <parallel>N</parallel>
- <xloc>570</xloc>
- <yloc>208</yloc>
- <attributes_hac/>
- </action>
<action>
<name>0002-http-client-test-headers.hpl</name>
<description/>
<type>PIPELINE</type>
<attributes/>
- <filename>${PROJECT_HOME}/0002-http-client-test-headers.hpl</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <clear_rows>N</clear_rows>
- <clear_files>N</clear_files>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
<add_date>N</add_date>
<add_time>N</add_time>
- <loglevel>Basic</loglevel>
- <set_append_logfile>N</set_append_logfile>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
+ <clear_files>N</clear_files>
+ <clear_rows>N</clear_rows>
<create_parent_folder>N</create_parent_folder>
- <run_configuration>local</run_configuration>
+ <exec_per_row>N</exec_per_row>
+ <filename>${PROJECT_HOME}/0002-http-client-test-headers.hpl</filename>
+ <loglevel>Basic</loglevel>
<parameters>
- <pass_all_parameters>Y</pass_all_parameters>
<parameter>
<name>HOSTNAME</name>
- <stream_name/>
<value>${HOSTNAME}</value>
</parameter>
+ <pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <params_from_previous>N</params_from_previous>
+ <run_configuration>local</run_configuration>
+ <set_append_logfile>N</set_append_logfile>
+ <set_logfile>N</set_logfile>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
<xloc>570</xloc>
<yloc>48</yloc>
@@ -137,35 +120,59 @@ limitations under the License.
<description/>
<type>PIPELINE</type>
<attributes/>
- <filename>${PROJECT_HOME}/0002-http-client-test-parameters.hpl</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <clear_rows>N</clear_rows>
- <clear_files>N</clear_files>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
<add_date>N</add_date>
<add_time>N</add_time>
- <loglevel>Basic</loglevel>
- <set_append_logfile>N</set_append_logfile>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
+ <clear_files>N</clear_files>
+ <clear_rows>N</clear_rows>
<create_parent_folder>N</create_parent_folder>
- <run_configuration>local</run_configuration>
+ <exec_per_row>N</exec_per_row>
+ <filename>${PROJECT_HOME}/0002-http-client-test-parameters.hpl</filename>
+ <loglevel>Basic</loglevel>
<parameters>
- <pass_all_parameters>Y</pass_all_parameters>
<parameter>
<name>HOSTNAME</name>
- <stream_name/>
<value>${HOSTNAME}</value>
</parameter>
+ <pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <params_from_previous>N</params_from_previous>
+ <run_configuration>local</run_configuration>
+ <set_append_logfile>N</set_append_logfile>
+ <set_logfile>N</set_logfile>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
<xloc>830</xloc>
<yloc>48</yloc>
<attributes_hac/>
</action>
+ <action>
+ <name>0002-http-client-test-empty-parameters.hpl</name>
+ <description/>
+ <type>PIPELINE</type>
+ <attributes/>
+ <add_date>N</add_date>
+ <add_time>N</add_time>
+ <clear_files>N</clear_files>
+ <clear_rows>N</clear_rows>
+ <create_parent_folder>N</create_parent_folder>
+ <exec_per_row>N</exec_per_row>
+
<filename>${PROJECT_HOME}/0002-http-client-test-empty-parameters.hpl</filename>
+ <logext/>
+ <logfile/>
+ <loglevel>Basic</loglevel>
+ <parameters>
+ <pass_all_parameters>Y</pass_all_parameters>
+ </parameters>
+ <params_from_previous>N</params_from_previous>
+ <run_configuration>local</run_configuration>
+ <set_append_logfile>N</set_append_logfile>
+ <set_logfile>N</set_logfile>
+ <wait_until_finished>Y</wait_until_finished>
+ <parallel>N</parallel>
+ <xloc>1120</xloc>
+ <yloc>48</yloc>
+ <attributes_hac/>
+ </action>
</actions>
<hops>
<hop>
@@ -175,13 +182,6 @@ limitations under the License.
<evaluation>Y</evaluation>
<unconditional>Y</unconditional>
</hop>
- <hop>
- <from>0002-http-client.hpl</from>
- <to>Abort workflow</to>
- <enabled>Y</enabled>
- <evaluation>N</evaluation>
- <unconditional>N</unconditional>
- </hop>
<hop>
<from>0002-http-client.hpl</from>
<to>0002-http-client-test-headers.hpl</to>
@@ -196,18 +196,11 @@ limitations under the License.
<evaluation>Y</evaluation>
<unconditional>N</unconditional>
</hop>
- <hop>
- <from>0002-http-client-test-headers.hpl</from>
- <to>Abort workflow</to>
- <enabled>Y</enabled>
- <evaluation>N</evaluation>
- <unconditional>N</unconditional>
- </hop>
<hop>
<from>0002-http-client-test-parameters.hpl</from>
- <to>Abort workflow</to>
+ <to>0002-http-client-test-empty-parameters.hpl</to>
<enabled>Y</enabled>
- <evaluation>N</evaluation>
+ <evaluation>Y</evaluation>
<unconditional>N</unconditional>
</hop>
</hops>
diff --git
a/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/Http.java
b/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/Http.java
index 95a702a0f7..18e37f9e2c 100644
---
a/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/Http.java
+++
b/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/Http.java
@@ -126,17 +126,17 @@ public class Http extends BaseTransform<HttpMeta,
HttpData> {
// Add Custom Http headers
if (data.useHeaderParameters) {
- for (int i = 0; i < data.header_parameters_nrs.length; i++) {
+ for (int i = 0; i < data.headerParametersNrs.length; i++) {
method.addHeader(
data.headerParameters[i].getName(),
- data.inputRowMeta.getString(rowData,
data.header_parameters_nrs[i]));
+ data.inputRowMeta.getString(rowData,
data.headerParametersNrs[i]));
if (isDebug()) {
logDebug(
BaseMessages.getString(
PKG,
"HTTPDialog.Log.HeaderValue",
data.headerParameters[i].getName(),
- data.inputRowMeta.getString(rowData,
data.header_parameters_nrs[i])));
+ data.inputRowMeta.getString(rowData,
data.headerParametersNrs[i])));
}
}
}
@@ -271,13 +271,12 @@ public class Http extends BaseTransform<HttpMeta,
HttpData> {
}
uriBuilder = new URIBuilder(baseUrl); // the base URL with variable
substitution
- List<NameValuePair> queryParams = uriBuilder.getQueryParams();
for (int i = 0; i < data.argnrs.length; i++) {
String key = meta.getArgumentParameter()[i];
String value = outputRowMeta.getString(row, data.argnrs[i]);
- if (!key.isEmpty() && !value.isEmpty()) {
- uriBuilder.addParameter(key, value);
+ if (!key.isEmpty()) {
+ uriBuilder.addParameter(key, Const.NVL(value, ""));
}
}
} catch (Exception e) {
@@ -337,7 +336,7 @@ public class Http extends BaseTransform<HttpMeta, HttpData>
{
data.useHeaderParameters = true;
}
- data.header_parameters_nrs = new int[nrHeaders];
+ data.headerParametersNrs = new int[nrHeaders];
data.headerParameters = new NameValuePair[nrHeaders];
// get the headers
@@ -353,11 +352,11 @@ public class Http extends BaseTransform<HttpMeta,
HttpData> {
PKG, CONST_HTTP_EXCEPTION_ERROR_FINDING_FIELD,
meta.getHeaderField()[i]));
}
- data.header_parameters_nrs[i] = fieldIndex;
+ data.headerParametersNrs[i] = fieldIndex;
data.headerParameters[i] =
new BasicNameValuePair(
resolve(meta.getHeaderParameter()[i]),
- data.outputRowMeta.getString(r,
data.header_parameters_nrs[i]));
+ data.outputRowMeta.getString(r, data.headerParametersNrs[i]));
}
} // end if first
diff --git
a/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpData.java
b/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpData.java
index f5a7b8661d..447f4dd1c9 100644
---
a/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpData.java
+++
b/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpData.java
@@ -33,7 +33,7 @@ public class HttpData extends BaseTransformData implements
ITransformData {
public int realProxyPort;
public String realHttpLogin;
public String realHttpPassword;
- public int[] header_parameters_nrs;
+ public int[] headerParametersNrs;
public boolean useHeaderParameters;
public NameValuePair[] headerParameters;
diff --git
a/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpMeta.java
b/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpMeta.java
index faf8e38657..fb7c6be510 100644
---
a/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpMeta.java
+++
b/plugins/transforms/http/src/main/java/org/apache/hop/pipeline/transforms/http/HttpMeta.java
@@ -18,6 +18,8 @@
package org.apache.hop.pipeline.transforms.http;
import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.CheckResult;
import org.apache.hop.core.Const;
import org.apache.hop.core.ICheckResult;
@@ -47,6 +49,8 @@ import org.w3c.dom.Node;
categoryDescription =
"i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Lookup",
keywords = "i18n::HttpMeta.keyword",
documentationUrl = "/pipeline/transforms/http.html")
+@Getter
+@Setter
public class HttpMeta extends BaseTransformMeta<Http, HttpData> {
private static final Class<?> PKG = HttpMeta.class;
@@ -108,162 +112,6 @@ public class HttpMeta extends BaseTransformMeta<Http,
HttpData> {
super(); // allocate BaseTransformMeta
}
- /**
- * @return Returns the connectionTimeout.
- */
- public String getConnectionTimeout() {
- return connectionTimeout;
- }
-
- /**
- * @param connectionTimeout The connectionTimeout to set.
- */
- public void setConnectionTimeout(String connectionTimeout) {
- this.connectionTimeout = connectionTimeout;
- }
-
- /**
- * @return Returns the closeIdleConnectionsTime.
- */
- public String getCloseIdleConnectionsTime() {
- return closeIdleConnectionsTime;
- }
-
- /**
- * @param closeIdleConnectionsTime The connectionTimeout to set.
- */
- public void setCloseIdleConnectionsTime(String closeIdleConnectionsTime) {
- this.closeIdleConnectionsTime = closeIdleConnectionsTime;
- }
-
- /**
- * @return Returns the socketTimeout.
- */
- public String getSocketTimeout() {
- return socketTimeout;
- }
-
- /**
- * @param socketTimeout The socketTimeout to set.
- */
- public void setSocketTimeout(String socketTimeout) {
- this.socketTimeout = socketTimeout;
- }
-
- /**
- * @return Returns the argument.
- */
- public String[] getArgumentField() {
- return argumentField;
- }
-
- /**
- * @param argument The argument to set.
- */
- public void setArgumentField(String[] argument) {
- this.argumentField = argument;
- }
-
- /**
- * @return Returns the headerFields.
- */
- public String[] getHeaderField() {
-
- return headerField;
- }
-
- /**
- * @param headerField The headerField to set.
- */
- public void setHeaderField(String[] headerField) {
-
- this.headerField = headerField;
- }
-
- /**
- * @return Returns the argumentDirection.
- */
- public String[] getArgumentParameter() {
- return argumentParameter;
- }
-
- /**
- * @param argumentDirection The argumentDirection to set.
- */
- public void setArgumentParameter(String[] argumentDirection) {
- this.argumentParameter = argumentDirection;
- }
-
- /**
- * @return Returns the headerParameter.
- */
- public String[] getHeaderParameter() {
- return headerParameter;
- }
-
- /**
- * @param headerParameter The headerParameter to set.
- */
- public void setHeaderParameter(String[] headerParameter) {
- this.headerParameter = headerParameter;
- }
-
- /**
- * @return Returns the procedure.
- */
- public String getUrl() {
- return url;
- }
-
- /**
- * @param procedure The procedure to set.
- */
- public void setUrl(String procedure) {
- this.url = procedure;
- }
-
- /**
- * @return Returns the resultName.
- */
- public String getFieldName() {
- return fieldName;
- }
-
- /**
- * @param resultName The resultName to set.
- */
- public void setFieldName(String resultName) {
- this.fieldName = resultName;
- }
-
- /**
- * @return Is the url coded in a field?
- */
- public boolean isUrlInField() {
- return urlInField;
- }
-
- /**
- * @param urlInField Is the url coded in a field?
- */
- public void setUrlInField(boolean urlInField) {
- this.urlInField = urlInField;
- }
-
- /**
- * @return The field name that contains the url.
- */
- public String getUrlField() {
- return urlField;
- }
-
- /**
- * @param urlField name of the field that contains the url
- */
- public void setUrlField(String urlField) {
- this.urlField = urlField;
- }
-
@Override
public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
throws HopXmlException {
@@ -527,126 +375,4 @@ public class HttpMeta extends BaseTransformMeta<Http,
HttpData> {
public boolean supportsErrorHandling() {
return true;
}
-
- /**
- * @return the encoding
- */
- public String getEncoding() {
- return encoding;
- }
-
- /**
- * @param encoding the encoding to set
- */
- public void setEncoding(String encoding) {
- this.encoding = encoding;
- }
-
- /**
- * ISetter
- *
- * @param proxyHost
- */
- public void setProxyHost(String proxyHost) {
- this.proxyHost = proxyHost;
- }
-
- /**
- * IGetter
- *
- * @return
- */
- public String getProxyHost() {
- return proxyHost;
- }
-
- /**
- * ISetter
- *
- * @param proxyPort
- */
- public void setProxyPort(String proxyPort) {
- this.proxyPort = proxyPort;
- }
-
- /**
- * IGetter
- *
- * @return
- */
- public String getProxyPort() {
- return this.proxyPort;
- }
-
- /**
- * ISetter
- *
- * @param httpLogin
- */
- public void setHttpLogin(String httpLogin) {
- this.httpLogin = httpLogin;
- }
-
- /**
- * IGetter
- *
- * @return
- */
- public String getHttpLogin() {
- return httpLogin;
- }
-
- /**
- * ISetter
- *
- * @param httpPassword
- */
- public void setHttpPassword(String httpPassword) {
- this.httpPassword = httpPassword;
- }
-
- /**
- * @return
- */
- public String getHttpPassword() {
- return httpPassword;
- }
-
- /**
- * @return the resultCodeFieldName
- */
- public String getResultCodeFieldName() {
- return resultCodeFieldName;
- }
-
- /**
- * @param resultCodeFieldName the resultCodeFieldName to set
- */
- public void setResultCodeFieldName(String resultCodeFieldName) {
- this.resultCodeFieldName = resultCodeFieldName;
- }
-
- public String getResponseTimeFieldName() {
- return responseTimeFieldName;
- }
-
- public void setResponseTimeFieldName(String responseTimeFieldName) {
- this.responseTimeFieldName = responseTimeFieldName;
- }
-
- public String getResponseHeaderFieldName() {
- return responseHeaderFieldName;
- }
-
- public void setResponseHeaderFieldName(String responseHeaderFieldName) {
- this.responseHeaderFieldName = responseHeaderFieldName;
- }
-
- public boolean isIgnoreSsl() {
- return ignoreSsl;
- }
-
- public void setIgnoreSsl(boolean ignoreSsl) {
- this.ignoreSsl = ignoreSsl;
- }
}
diff --git
a/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpDataTest.java
b/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpDataTest.java
new file mode 100644
index 0000000000..a222711b6b
--- /dev/null
+++
b/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpDataTest.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.http;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.junit.rules.RestoreHopEnvironmentExtension;
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(RestoreHopEnvironmentExtension.class)
+class HttpDataTest {
+
+ private HttpData data;
+
+ @BeforeEach
+ void setUp() {
+ data = new HttpData();
+ }
+
+ @Test
+ void testDefaultConstructor() {
+ assertNotNull(data, "HttpData should not be null");
+ assertEquals(-1, data.indexOfUrlField, "indexOfUrlField should be -1 by
default");
+ assertNull(data.realProxyHost, "realProxyHost should be null by default");
+ assertEquals(8080, data.realProxyPort, "realProxyPort should be 8080 by
default");
+ assertNull(data.realHttpLogin, "realHttpLogin should be null by default");
+ assertNull(data.realHttpPassword, "realHttpPassword should be null by
default");
+ }
+
+ @Test
+ void testIndexOfUrlField() {
+ data.indexOfUrlField = 5;
+ assertEquals(5, data.indexOfUrlField);
+
+ data.indexOfUrlField = -1;
+ assertEquals(-1, data.indexOfUrlField);
+ }
+
+ @Test
+ void testRealUrl() {
+ assertNull(data.realUrl, "realUrl should be null initially");
+
+ data.realUrl = "http://example.com";
+ assertEquals("http://example.com", data.realUrl);
+ }
+
+ @Test
+ void testRealProxyHost() {
+ assertNull(data.realProxyHost, "realProxyHost should be null by default");
+
+ data.realProxyHost = "proxy.example.com";
+ assertEquals("proxy.example.com", data.realProxyHost);
+ }
+
+ @Test
+ void testRealProxyPort() {
+ assertEquals(8080, data.realProxyPort, "Default proxy port should be
8080");
+
+ data.realProxyPort = 3128;
+ assertEquals(3128, data.realProxyPort);
+ }
+
+ @Test
+ void testRealHttpLogin() {
+ assertNull(data.realHttpLogin, "realHttpLogin should be null by default");
+
+ data.realHttpLogin = "username";
+ assertEquals("username", data.realHttpLogin);
+ }
+
+ @Test
+ void testRealHttpPassword() {
+ assertNull(data.realHttpPassword, "realHttpPassword should be null by
default");
+
+ data.realHttpPassword = "password123";
+ assertEquals("password123", data.realHttpPassword);
+ }
+
+ @Test
+ void testArgnrs() {
+ assertNull(data.argnrs, "argnrs should be null initially");
+
+ data.argnrs = new int[] {0, 1, 2};
+ assertEquals(3, data.argnrs.length);
+ assertEquals(0, data.argnrs[0]);
+ assertEquals(1, data.argnrs[1]);
+ assertEquals(2, data.argnrs[2]);
+ }
+
+ @Test
+ void testOutputRowMeta() {
+ assertNull(data.outputRowMeta, "outputRowMeta should be null initially");
+
+ data.outputRowMeta = new RowMeta();
+ assertNotNull(data.outputRowMeta);
+ }
+
+ @Test
+ void testInputRowMeta() {
+ assertNull(data.inputRowMeta, "inputRowMeta should be null initially");
+
+ data.inputRowMeta = new RowMeta();
+ assertNotNull(data.inputRowMeta);
+ }
+
+ @Test
+ void testHeaderParametersNrs() {
+ assertNull(data.headerParametersNrs, "headerParametersNrs should be null
initially");
+
+ data.headerParametersNrs = new int[] {1, 3, 5};
+ assertEquals(3, data.headerParametersNrs.length);
+ assertEquals(1, data.headerParametersNrs[0]);
+ assertEquals(3, data.headerParametersNrs[1]);
+ assertEquals(5, data.headerParametersNrs[2]);
+ }
+
+ @Test
+ void testUseHeaderParameters() {
+ assertFalse(data.useHeaderParameters, "useHeaderParameters should be false
by default");
+
+ data.useHeaderParameters = true;
+ assertEquals(true, data.useHeaderParameters);
+ }
+
+ @Test
+ void testHeaderParameters() {
+ assertNull(data.headerParameters, "headerParameters should be null
initially");
+
+ NameValuePair[] params =
+ new NameValuePair[] {
+ new BasicNameValuePair("Authorization", "Bearer token"),
+ new BasicNameValuePair("Content-Type", "application/json")
+ };
+ data.headerParameters = params;
+
+ assertNotNull(data.headerParameters);
+ assertEquals(2, data.headerParameters.length);
+ assertEquals("Authorization", data.headerParameters[0].getName());
+ assertEquals("Bearer token", data.headerParameters[0].getValue());
+ }
+
+ @Test
+ void testRealSocketTimeout() {
+ assertEquals(0, data.realSocketTimeout, "realSocketTimeout should be 0
initially");
+
+ data.realSocketTimeout = 5000;
+ assertEquals(5000, data.realSocketTimeout);
+ }
+
+ @Test
+ void testRealConnectionTimeout() {
+ assertEquals(0, data.realConnectionTimeout, "realConnectionTimeout should
be 0 initially");
+
+ data.realConnectionTimeout = 3000;
+ assertEquals(3000, data.realConnectionTimeout);
+ }
+
+ @Test
+ void testWithoutPreviousTransforms() {
+ assertFalse(
+ data.withoutPreviousTransforms, "withoutPreviousTransforms should be
false by default");
+
+ data.withoutPreviousTransforms = true;
+ assertTrue(data.withoutPreviousTransforms);
+ }
+
+ @Test
+ void testMultipleFieldsSetAndGet() {
+ // Set multiple fields
+ data.indexOfUrlField = 10;
+ data.realUrl = "http://api.example.com";
+ data.realProxyHost = "proxy.corp.com";
+ data.realProxyPort = 9090;
+ data.realHttpLogin = "admin";
+ data.realHttpPassword = "secret";
+ data.realSocketTimeout = 15000;
+ data.realConnectionTimeout = 8000;
+ data.useHeaderParameters = true;
+ data.withoutPreviousTransforms = true;
+
+ // Verify all fields
+ assertEquals(10, data.indexOfUrlField);
+ assertEquals("http://api.example.com", data.realUrl);
+ assertEquals("proxy.corp.com", data.realProxyHost);
+ assertEquals(9090, data.realProxyPort);
+ assertEquals("admin", data.realHttpLogin);
+ assertEquals("secret", data.realHttpPassword);
+ assertEquals(15000, data.realSocketTimeout);
+ assertEquals(8000, data.realConnectionTimeout);
+ assertTrue(data.useHeaderParameters);
+ assertTrue(data.withoutPreviousTransforms);
+ }
+
+ @Test
+ void testArgnrsWithEmptyArray() {
+ data.argnrs = new int[0];
+ assertNotNull(data.argnrs);
+ assertEquals(0, data.argnrs.length);
+ }
+
+ @Test
+ void testHeaderParametersWithEmptyArray() {
+ data.headerParameters = new NameValuePair[0];
+ assertNotNull(data.headerParameters);
+ assertEquals(0, data.headerParameters.length);
+ }
+
+ @Test
+ void testNegativeIndexOfUrlField() {
+ data.indexOfUrlField = -999;
+ assertEquals(-999, data.indexOfUrlField);
+ }
+
+ @Test
+ void testZeroTimeouts() {
+ data.realSocketTimeout = 0;
+ data.realConnectionTimeout = 0;
+
+ assertEquals(0, data.realSocketTimeout);
+ assertEquals(0, data.realConnectionTimeout);
+ }
+
+ @Test
+ void testLargeTimeouts() {
+ data.realSocketTimeout = Integer.MAX_VALUE;
+ data.realConnectionTimeout = Integer.MAX_VALUE;
+
+ assertEquals(Integer.MAX_VALUE, data.realSocketTimeout);
+ assertEquals(Integer.MAX_VALUE, data.realConnectionTimeout);
+ }
+}
diff --git
a/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpMetaTest.java
b/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpMetaTest.java
new file mode 100644
index 0000000000..f78f5f2ec3
--- /dev/null
+++
b/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpMetaTest.java
@@ -0,0 +1,341 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.pipeline.transforms.http;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.hop.core.ICheckResult;
+import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.variables.Variables;
+import org.apache.hop.junit.rules.RestoreHopEnvironmentExtension;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.pipeline.transform.TransformMeta;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(RestoreHopEnvironmentExtension.class)
+class HttpMetaTest {
+
+ private HttpMeta meta;
+
+ @BeforeEach
+ void setUp() {
+ meta = new HttpMeta();
+ }
+
+ @Test
+ void testSetDefault() {
+ meta.setDefault();
+
+ assertEquals(String.valueOf(HttpMeta.DEFAULT_SOCKET_TIMEOUT),
meta.getSocketTimeout());
+ assertEquals(String.valueOf(HttpMeta.DEFAULT_CONNECTION_TIMEOUT),
meta.getConnectionTimeout());
+ assertEquals(
+ String.valueOf(HttpMeta.DEFAULT_CLOSE_CONNECTIONS_TIME),
+ meta.getCloseIdleConnectionsTime());
+ assertEquals("result", meta.getFieldName());
+ assertEquals("UTF-8", meta.getEncoding());
+ assertEquals("", meta.getResultCodeFieldName());
+ assertEquals("", meta.getResponseTimeFieldName());
+ assertEquals("", meta.getResponseHeaderFieldName());
+ }
+
+ @Test
+ void testUrlConfiguration() {
+ // Test URL properties
+ meta.setUrl("http://example.com");
+ assertEquals("http://example.com", meta.getUrl());
+
+ meta.setUrlInField(true);
+ assertTrue(meta.isUrlInField());
+
+ meta.setUrlField("urlColumn");
+ assertEquals("urlColumn", meta.getUrlField());
+
+ meta.setUrlInField(false);
+ assertFalse(meta.isUrlInField());
+ }
+
+ @Test
+ void testOutputFieldConfiguration() {
+ // Test all output field properties
+ meta.setFieldName("resultField");
+ assertEquals("resultField", meta.getFieldName());
+
+ meta.setResultCodeFieldName("responseCode");
+ assertEquals("responseCode", meta.getResultCodeFieldName());
+
+ meta.setResponseTimeFieldName("responseTime");
+ assertEquals("responseTime", meta.getResponseTimeFieldName());
+
+ meta.setResponseHeaderFieldName("responseHeader");
+ assertEquals("responseHeader", meta.getResponseHeaderFieldName());
+ }
+
+ @Test
+ void testProxyAndAuthConfiguration() {
+ // Test proxy and authentication properties
+ meta.setProxyHost("proxy.example.com");
+ assertEquals("proxy.example.com", meta.getProxyHost());
+
+ meta.setProxyPort("8080");
+ assertEquals("8080", meta.getProxyPort());
+
+ meta.setHttpLogin("username");
+ assertEquals("username", meta.getHttpLogin());
+
+ meta.setHttpPassword("password123");
+ assertEquals("password123", meta.getHttpPassword());
+ }
+
+ @Test
+ void testTimeoutAndConnectionConfiguration() {
+ // Test timeout and connection properties
+ meta.setSocketTimeout("5000");
+ assertEquals("5000", meta.getSocketTimeout());
+
+ meta.setConnectionTimeout("3000");
+ assertEquals("3000", meta.getConnectionTimeout());
+
+ meta.setCloseIdleConnectionsTime("10000");
+ assertEquals("10000", meta.getCloseIdleConnectionsTime());
+
+ meta.setEncoding("ISO-8859-1");
+ assertEquals("ISO-8859-1", meta.getEncoding());
+
+ meta.setIgnoreSsl(true);
+ assertTrue(meta.isIgnoreSsl());
+
+ meta.setIgnoreSsl(false);
+ assertFalse(meta.isIgnoreSsl());
+ }
+
+ @Test
+ void testArgumentsAndHeadersConfiguration() {
+ // Test allocate
+ meta.allocate(3, 2);
+ assertNotNull(meta.getArgumentField());
+ assertNotNull(meta.getArgumentParameter());
+ assertNotNull(meta.getHeaderField());
+ assertNotNull(meta.getHeaderParameter());
+ assertEquals(3, meta.getArgumentField().length);
+ assertEquals(3, meta.getArgumentParameter().length);
+ assertEquals(2, meta.getHeaderField().length);
+ assertEquals(2, meta.getHeaderParameter().length);
+
+ // Test argument fields and parameters
+ String[] argFields = {"field1", "field2", "field3"};
+ meta.setArgumentField(argFields);
+ assertEquals(3, meta.getArgumentField().length);
+ assertEquals("field1", meta.getArgumentField()[0]);
+ assertEquals("field2", meta.getArgumentField()[1]);
+
+ String[] argParams = {"param1", "param2"};
+ meta.setArgumentParameter(argParams);
+ assertEquals("param1", meta.getArgumentParameter()[0]);
+ assertEquals("param2", meta.getArgumentParameter()[1]);
+
+ // Test header fields and parameters
+ String[] headerFields = {"Authorization", "Content-Type"};
+ meta.setHeaderField(headerFields);
+ assertEquals(2, meta.getHeaderField().length);
+ assertEquals("Authorization", meta.getHeaderField()[0]);
+
+ String[] headerParams = {"Bearer token", "application/json"};
+ meta.setHeaderParameter(headerParams);
+ assertEquals(2, meta.getHeaderParameter().length);
+ assertEquals("Bearer token", meta.getHeaderParameter()[0]);
+ }
+
+ @Test
+ void testClone() {
+ meta.allocate(2, 1);
+ meta.setUrl("http://test.com");
+ meta.setFieldName("output");
+ meta.getArgumentField()[0] = "arg1";
+ meta.getArgumentField()[1] = "arg2";
+ meta.getArgumentParameter()[0] = "param1";
+ meta.getArgumentParameter()[1] = "param2";
+ meta.getHeaderField()[0] = "header1";
+ meta.getHeaderParameter()[0] = "value1";
+
+ HttpMeta cloned = (HttpMeta) meta.clone();
+
+ assertNotNull(cloned);
+ assertEquals(meta.getUrl(), cloned.getUrl());
+ assertEquals(meta.getFieldName(), cloned.getFieldName());
+ assertEquals(2, cloned.getArgumentField().length);
+ assertEquals("arg1", cloned.getArgumentField()[0]);
+ assertEquals("arg2", cloned.getArgumentField()[1]);
+ }
+
+ @Test
+ void testGetFields() throws Exception {
+ Variables variables = new Variables();
+
+ // Test with all fields configured
+ meta.setFieldName("resultField");
+ meta.setResultCodeFieldName("statusCode");
+ meta.setResponseTimeFieldName("responseTime");
+ meta.setResponseHeaderFieldName("headers");
+
+ IRowMeta rowMetaAll = new RowMeta();
+ meta.getFields(rowMetaAll, "HttpTransform", null, null, variables, null);
+ assertEquals(4, rowMetaAll.size());
+ assertNotNull(rowMetaAll.searchValueMeta("resultField"));
+ assertNotNull(rowMetaAll.searchValueMeta("statusCode"));
+ assertNotNull(rowMetaAll.searchValueMeta("responseTime"));
+ assertNotNull(rowMetaAll.searchValueMeta("headers"));
+ assertEquals("HttpTransform",
rowMetaAll.searchValueMeta("resultField").getOrigin());
+
+ // Test with empty field names
+ meta.setFieldName("");
+ meta.setResultCodeFieldName("");
+ meta.setResponseTimeFieldName("");
+ meta.setResponseHeaderFieldName("");
+ IRowMeta rowMetaEmpty = new RowMeta();
+ meta.getFields(rowMetaEmpty, "HttpTransform", null, null, variables, null);
+ assertEquals(0, rowMetaEmpty.size());
+
+ // Test with only result field
+ meta.setFieldName("result");
+ IRowMeta rowMetaSingle = new RowMeta();
+ meta.getFields(rowMetaSingle, "HttpTransform", null, null, variables,
null);
+ assertEquals(1, rowMetaSingle.size());
+ assertNotNull(rowMetaSingle.searchValueMeta("result"));
+ }
+
+ @Test
+ void testGetXml() {
+ meta.allocate(1, 1);
+ meta.setUrl("http://example.com");
+ meta.setUrlInField(true);
+ meta.setUrlField("urlField");
+ meta.setEncoding("UTF-8");
+ meta.setHttpLogin("user");
+ meta.setHttpPassword("pass");
+ meta.setProxyHost("proxy");
+ meta.setProxyPort("8080");
+ meta.getArgumentField()[0] = "arg1";
+ meta.getArgumentParameter()[0] = "param1";
+ meta.getHeaderField()[0] = "header1";
+ meta.getHeaderParameter()[0] = "value1";
+ meta.setFieldName("result");
+ meta.setResultCodeFieldName("code");
+
+ String xml = meta.getXml();
+
+ assertNotNull(xml);
+ assertTrue(xml.contains("<url>http://example.com</url>"));
+ assertTrue(xml.contains("<urlInField>Y</urlInField>"));
+ assertTrue(xml.contains("<urlField>urlField</urlField>"));
+ assertTrue(xml.contains("<encoding>UTF-8</encoding>"));
+ assertTrue(xml.contains("<httpLogin>user</httpLogin>"));
+ assertTrue(xml.contains("<proxyHost>proxy</proxyHost>"));
+ assertTrue(xml.contains("<proxyPort>8080</proxyPort>"));
+ assertTrue(xml.contains("<name>arg1</name>"));
+ assertTrue(xml.contains("<parameter>param1</parameter>"));
+ assertTrue(xml.contains("<name>result</name>"));
+ assertTrue(xml.contains("<code>code</code>"));
+ }
+
+ @Test
+ void testCheckValidation() {
+ TransformMeta transformMeta = mock(TransformMeta.class);
+ PipelineMeta pipelineMeta = mock(PipelineMeta.class);
+ IRowMeta prev = mock(IRowMeta.class);
+ List<ICheckResult> remarks;
+
+ // Test with input transform
+ remarks = new ArrayList<>();
+ meta.check(
+ remarks, pipelineMeta, transformMeta, prev, new String[] {"prev"},
null, null, null, null);
+ assertTrue(remarks.size() > 0);
+ assertTrue(remarks.stream().anyMatch(r -> r.getType() ==
ICheckResult.TYPE_RESULT_OK));
+
+ // Test without input transform
+ remarks = new ArrayList<>();
+ meta.check(remarks, pipelineMeta, transformMeta, prev, new String[] {},
null, null, null, null);
+ assertTrue(remarks.stream().anyMatch(r -> r.getType() ==
ICheckResult.TYPE_RESULT_ERROR));
+
+ // Test URL in field - missing field name
+ remarks = new ArrayList<>();
+ meta.setUrlInField(true);
+ meta.setUrlField("");
+ meta.check(
+ remarks, pipelineMeta, transformMeta, prev, new String[] {"prev"},
null, null, null, null);
+ assertTrue(remarks.stream().anyMatch(r -> r.getType() ==
ICheckResult.TYPE_RESULT_ERROR));
+
+ // Test URL in field - with field name
+ remarks = new ArrayList<>();
+ meta.setUrlField("urlColumn");
+ meta.check(
+ remarks, pipelineMeta, transformMeta, prev, new String[] {"prev"},
null, null, null, null);
+ assertFalse(remarks.isEmpty());
+
+ // Test URL not in field - missing URL
+ remarks = new ArrayList<>();
+ meta.setUrlInField(false);
+ meta.setUrl("");
+ meta.check(
+ remarks, pipelineMeta, transformMeta, prev, new String[] {"prev"},
null, null, null, null);
+ assertTrue(remarks.stream().anyMatch(r -> r.getType() ==
ICheckResult.TYPE_RESULT_ERROR));
+
+ // Test URL not in field - with URL
+ remarks = new ArrayList<>();
+ meta.setUrl("http://example.com");
+ meta.check(
+ remarks, pipelineMeta, transformMeta, prev, new String[] {"prev"},
null, null, null, null);
+ assertTrue(remarks.stream().anyMatch(r -> r.getType() ==
ICheckResult.TYPE_RESULT_OK));
+ }
+
+ @Test
+ void testMiscellaneous() {
+ // Test error handling support
+ assertTrue(meta.supportsErrorHandling());
+
+ // Test constants
+ assertEquals(10000, HttpMeta.DEFAULT_SOCKET_TIMEOUT);
+ assertEquals(10000, HttpMeta.DEFAULT_CONNECTION_TIMEOUT);
+ assertEquals(HttpMeta.DEFAULT_CLOSE_CONNECTIONS_TIME, -1);
+ assertEquals("header", HttpMeta.CONST_HEADER);
+ assertEquals("result", HttpMeta.CONST_RESULT);
+ assertEquals(" ", HttpMeta.CONST_SPACES_LONG);
+ assertEquals(" ", HttpMeta.CONST_SPACES);
+ assertEquals("parameter", HttpMeta.CONST_PARAMETER);
+
+ // Test allocate with zero
+ meta.allocate(0, 0);
+ assertEquals(0, meta.getArgumentField().length);
+ assertEquals(0, meta.getArgumentParameter().length);
+ assertEquals(0, meta.getHeaderField().length);
+ assertEquals(0, meta.getHeaderParameter().length);
+
+ // Test clone without allocation
+ HttpMeta cloned = (HttpMeta) meta.clone();
+ assertNotNull(cloned);
+ assertEquals(0, cloned.getArgumentField().length);
+ }
+}
diff --git
a/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpTest.java
b/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpTest.java
index a24d82f095..f73c4dd0a1 100644
---
a/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpTest.java
+++
b/plugins/transforms/http/src/test/java/org/apache/hop/pipeline/transforms/http/HttpTest.java
@@ -18,102 +18,653 @@
package org.apache.hop.pipeline.transforms.http;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.net.HttpURLConnection;
-import org.apache.hop.core.logging.ILogChannel;
+import java.nio.charset.StandardCharsets;
+import org.apache.hop.core.logging.ILoggingObject;
import org.apache.hop.core.row.IRowMeta;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.row.value.ValueMetaString;
import org.apache.hop.core.util.HttpClientManager;
+import org.apache.hop.junit.rules.RestoreHopEnvironmentExtension;
+import org.apache.hop.pipeline.transforms.mock.TransformMockHelper;
import org.apache.http.Header;
+import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
+import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HttpContext;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
+@ExtendWith(RestoreHopEnvironmentExtension.class)
class HttpTest {
- private static MockedStatic<HttpClientManager> mockedHttpClientManager;
+ private TransformMockHelper<HttpMeta, HttpData> transformMockHelper;
+ private Http httpTransform;
+ private HttpMeta httpMeta;
+ private HttpData httpData;
- private final ILogChannel log = mock(ILogChannel.class);
- private final IRowMeta rmi = mock(IRowMeta.class);
- private final HttpData data = mock(HttpData.class);
- private final HttpMeta meta = mock(HttpMeta.class);
- private final Http http = mock(Http.class);
-
- private final String DATA =
- "This is the description, there's some HTML here, like
<strong>this</strong>. "
- + "Sometimes this text is another language that might contain these
characters:\n"
- + "<p>é, è, ô, ç, à, ê, â.</p> They can, of course, come
in uppercase as well: <p>É, È Ô, Ç, À,"
- + " Ê, Â</p>. UTF-8 handles this well.";
+ private static final String TEST_RESPONSE_BODY = "Test response from HTTP
server";
+ private static final String TEST_URL = "http://example.com/api";
@BeforeEach
- void setup() throws Exception {
- HttpClientManager.HttpClientBuilderFacade builder =
- mock(HttpClientManager.HttpClientBuilderFacade.class);
+ void setUp() throws Exception {
+ transformMockHelper = new TransformMockHelper<>("HTTP Test",
HttpMeta.class, HttpData.class);
+ when(transformMockHelper.logChannelFactory.create(any(),
any(ILoggingObject.class)))
+ .thenReturn(transformMockHelper.iLogChannel);
+ when(transformMockHelper.pipeline.isRunning()).thenReturn(true);
+
+ // Mock getPrevTransforms to return an array with one element by default
+ when(transformMockHelper.pipelineMeta.getPrevTransforms(any()))
+ .thenReturn(new org.apache.hop.pipeline.transform.TransformMeta[1]);
+
+ httpMeta = new HttpMeta();
+ httpMeta.setDefault();
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("response");
+ httpMeta.allocate(0, 0);
+
+ httpData = new HttpData();
+
+ httpTransform =
+ new Http(
+ transformMockHelper.transformMeta,
+ httpMeta,
+ httpData,
+ 0,
+ transformMockHelper.pipelineMeta,
+ transformMockHelper.pipeline);
+ }
+
+ @AfterEach
+ void tearDown() {
+ transformMockHelper.cleanUp();
+ }
+
+ @Test
+ void testProcessRowWithNullRow() throws Exception {
+ // Create a spy to mock getRow()
+ Http httpSpy = spy(httpTransform);
+ doReturn(null).when(httpSpy).getRow();
+
+ // Process row - should return false when no more rows
+ boolean result = httpSpy.processRow();
+
+ assertFalse(result, "processRow should return false when row is null");
+ }
+
+ @Test
+ void testProcessRowFullExecution() throws Exception {
+ // Configure meta
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("responseBody");
+ httpMeta.setResultCodeFieldName("statusCode");
+ httpMeta.allocate(0, 0);
+
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("id"));
+ Object[] inputRow = new Object[] {"test123"};
+
+ // Mock HttpClientManager for the full execution
+ try (MockedStatic<HttpClientManager> mockedManager =
mockStatic(HttpClientManager.class)) {
+ HttpClientManager mockManager = mock(HttpClientManager.class);
+ HttpClientManager.HttpClientBuilderFacade mockBuilder =
+ mock(HttpClientManager.HttpClientBuilderFacade.class);
+ CloseableHttpClient mockClient = mock(CloseableHttpClient.class);
+ CloseableHttpResponse mockResponse = mock(CloseableHttpResponse.class);
+
+
mockedManager.when(HttpClientManager::getInstance).thenReturn(mockManager);
+ when(mockManager.createBuilder()).thenReturn(mockBuilder);
+ doReturn(mockBuilder).when(mockBuilder).setConnectionTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setSocketTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setCredentials(anyString(),
anyString());
+ doReturn(mockBuilder).when(mockBuilder).setProxy(anyString(), anyInt());
+
org.mockito.Mockito.doNothing().when(mockBuilder).ignoreSsl(anyBoolean());
+ when(mockBuilder.build()).thenReturn(mockClient);
+
+ // Mock HTTP response
+ StatusLine mockStatusLine = mock(StatusLine.class);
+
when(mockStatusLine.getStatusCode()).thenReturn(HttpURLConnection.HTTP_OK);
+ when(mockResponse.getStatusLine()).thenReturn(mockStatusLine);
+
+ HttpEntity mockEntity = mock(HttpEntity.class);
+ when(mockEntity.getContent())
+ .thenReturn(
+ new ByteArrayInputStream("Success
response".getBytes(StandardCharsets.UTF_8)));
+ when(mockResponse.getEntity()).thenReturn(mockEntity);
+ when(mockResponse.getAllHeaders()).thenReturn(new Header[0]);
+
+ when(mockClient.execute(any(HttpHost.class), any(HttpRequest.class),
any(HttpContext.class)))
+ .thenReturn(mockResponse);
+
+ // Create spy to mock getRow and capture putRow
+ Http httpSpy = spy(httpTransform);
+ doReturn(inputRow).doReturn(null).when(httpSpy).getRow();
+ doReturn(inputRowMeta).when(httpSpy).getInputRowMeta();
+
+ // Capture output
+ final Object[][] outputRows = new Object[1][];
+ org.mockito.Mockito.doAnswer(
+ invocation -> {
+ outputRows[0] = invocation.getArgument(1);
+ return null;
+ })
+ .when(httpSpy)
+ .putRow(any(IRowMeta.class), any(Object[].class));
+
+ // Initialize and process
+ httpSpy.init();
+ boolean result1 = httpSpy.processRow();
+ boolean result2 = httpSpy.processRow();
+
+ // Verify
+ assertTrue(result1, "First processRow should return true");
+ assertFalse(result2, "Second processRow should return false (no more
rows)");
+ assertNotNull(outputRows[0], "Output row should be captured");
+ assertTrue(outputRows[0].length >= 3, "Output should have input +
response fields");
+ assertEquals("test123", outputRows[0][0], "First field should be input
ID");
+ assertEquals("Success response", outputRows[0][1], "Second field should
be response body");
+ assertEquals(200L, outputRows[0][2], "Third field should be status
code");
+ }
+ }
+
+ @Test
+ void testProcessRowWithQueryParameters() throws Exception {
+ // Configure meta with query parameters
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("response");
+ httpMeta.allocate(2, 0);
+ httpMeta.getArgumentField()[0] = "userId";
+ httpMeta.getArgumentField()[1] = "action";
+ httpMeta.getArgumentParameter()[0] = "id";
+ httpMeta.getArgumentParameter()[1] = "action";
+
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("userId"));
+ inputRowMeta.addValueMeta(new ValueMetaString("action"));
+ Object[] inputRow = new Object[] {"user123", "view"};
+
+ // Mock HttpClientManager
+ try (MockedStatic<HttpClientManager> mockedManager =
mockStatic(HttpClientManager.class)) {
+ HttpClientManager mockManager = mock(HttpClientManager.class);
+ HttpClientManager.HttpClientBuilderFacade mockBuilder =
+ mock(HttpClientManager.HttpClientBuilderFacade.class);
+ CloseableHttpClient mockClient = mock(CloseableHttpClient.class);
+ CloseableHttpResponse mockResponse = mock(CloseableHttpResponse.class);
+
+
mockedManager.when(HttpClientManager::getInstance).thenReturn(mockManager);
+ when(mockManager.createBuilder()).thenReturn(mockBuilder);
+ doReturn(mockBuilder).when(mockBuilder).setConnectionTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setSocketTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setCredentials(anyString(),
anyString());
+ doReturn(mockBuilder).when(mockBuilder).setProxy(anyString(), anyInt());
+
org.mockito.Mockito.doNothing().when(mockBuilder).ignoreSsl(anyBoolean());
+ when(mockBuilder.build()).thenReturn(mockClient);
+
+ StatusLine mockStatusLine = mock(StatusLine.class);
+
when(mockStatusLine.getStatusCode()).thenReturn(HttpURLConnection.HTTP_OK);
+ when(mockResponse.getStatusLine()).thenReturn(mockStatusLine);
+
+ HttpEntity mockEntity = mock(HttpEntity.class);
+ when(mockEntity.getContent())
+ .thenReturn(new ByteArrayInputStream("Query
result".getBytes(StandardCharsets.UTF_8)));
+ when(mockResponse.getEntity()).thenReturn(mockEntity);
+ when(mockResponse.getAllHeaders()).thenReturn(new Header[0]);
+
+ when(mockClient.execute(any(HttpHost.class), any(HttpRequest.class),
any(HttpContext.class)))
+ .thenReturn(mockResponse);
+
+ // Create spy
+ Http httpSpy = spy(httpTransform);
+ doReturn(inputRow).doReturn(null).when(httpSpy).getRow();
+ doReturn(inputRowMeta).when(httpSpy).getInputRowMeta();
+
+ final Object[][] outputRows = new Object[1][];
+ org.mockito.Mockito.doAnswer(
+ invocation -> {
+ outputRows[0] = invocation.getArgument(1);
+ return null;
+ })
+ .when(httpSpy)
+ .putRow(any(IRowMeta.class), any(Object[].class));
+
+ // Initialize and process
+ httpSpy.init();
+ boolean result = httpSpy.processRow();
+
+ // Verify
+ assertTrue(result, "processRow should return true");
+ assertNotNull(outputRows[0], "Output row should be captured");
+ assertEquals("user123", outputRows[0][0], "First field should be
userId");
+ assertEquals("view", outputRows[0][1], "Second field should be action");
+ assertEquals("Query result", outputRows[0][2], "Third field should be
response");
+ }
+ }
+
+ @Test
+ void testProcessRowWithHeaders() throws Exception {
+ // Configure meta with custom headers
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("response");
+ httpMeta.allocate(0, 1);
+ httpMeta.getHeaderField()[0] = "authToken";
+ httpMeta.getHeaderParameter()[0] = "Authorization";
+
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("authToken"));
+ Object[] inputRow = new Object[] {"Bearer token123"};
+
+ // Mock HttpClientManager
+ try (MockedStatic<HttpClientManager> mockedManager =
mockStatic(HttpClientManager.class)) {
+ HttpClientManager mockManager = mock(HttpClientManager.class);
+ HttpClientManager.HttpClientBuilderFacade mockBuilder =
+ mock(HttpClientManager.HttpClientBuilderFacade.class);
+ CloseableHttpClient mockClient = mock(CloseableHttpClient.class);
+ CloseableHttpResponse mockResponse = mock(CloseableHttpResponse.class);
+
+
mockedManager.when(HttpClientManager::getInstance).thenReturn(mockManager);
+ when(mockManager.createBuilder()).thenReturn(mockBuilder);
+ doReturn(mockBuilder).when(mockBuilder).setConnectionTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setSocketTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setCredentials(anyString(),
anyString());
+ doReturn(mockBuilder).when(mockBuilder).setProxy(anyString(), anyInt());
+
org.mockito.Mockito.doNothing().when(mockBuilder).ignoreSsl(anyBoolean());
+ when(mockBuilder.build()).thenReturn(mockClient);
+
+ StatusLine mockStatusLine = mock(StatusLine.class);
+
when(mockStatusLine.getStatusCode()).thenReturn(HttpURLConnection.HTTP_OK);
+ when(mockResponse.getStatusLine()).thenReturn(mockStatusLine);
+
+ HttpEntity mockEntity = mock(HttpEntity.class);
+ when(mockEntity.getContent())
+ .thenReturn(new
ByteArrayInputStream("Authorized".getBytes(StandardCharsets.UTF_8)));
+ when(mockResponse.getEntity()).thenReturn(mockEntity);
+ when(mockResponse.getAllHeaders()).thenReturn(new Header[0]);
+
+ when(mockClient.execute(any(HttpHost.class), any(HttpRequest.class),
any(HttpContext.class)))
+ .thenReturn(mockResponse);
+
+ // Create spy
+ Http httpSpy = spy(httpTransform);
+ doReturn(inputRow).doReturn(null).when(httpSpy).getRow();
+ doReturn(inputRowMeta).when(httpSpy).getInputRowMeta();
+
+ final Object[][] outputRows = new Object[1][];
+ org.mockito.Mockito.doAnswer(
+ invocation -> {
+ outputRows[0] = invocation.getArgument(1);
+ return null;
+ })
+ .when(httpSpy)
+ .putRow(any(IRowMeta.class), any(Object[].class));
+
+ // Initialize and process
+ httpSpy.init();
+ boolean result = httpSpy.processRow();
+
+ // Verify
+ assertTrue(result, "processRow should return true");
+ assertNotNull(outputRows[0], "Output row should be captured");
+ assertEquals("Bearer token123", outputRows[0][0], "First field should be
auth token");
+ assertEquals("Authorized", outputRows[0][1], "Second field should be
response");
+ }
+ }
+
+ @Test
+ void testInit() {
+ httpMeta.setProxyHost("proxy.example.com");
+ httpMeta.setProxyPort("8080");
+ httpMeta.setHttpLogin("user");
+ httpMeta.setHttpPassword("password");
+ httpMeta.setSocketTimeout("5000");
+ httpMeta.setConnectionTimeout("3000");
+
+ boolean result = httpTransform.init();
+
+ assertTrue(result, "init should return true");
+ assertEquals("proxy.example.com", httpData.realProxyHost);
+ assertEquals(8080, httpData.realProxyPort);
+ assertEquals("user", httpData.realHttpLogin);
+ assertEquals("password", httpData.realHttpPassword);
+ assertEquals(5000, httpData.realSocketTimeout);
+ assertEquals(3000, httpData.realConnectionTimeout);
+ }
+
+ @Test
+ void testRequestStatusCode() {
+ CloseableHttpResponse response = mock(CloseableHttpResponse.class);
+ StatusLine statusLine = mock(StatusLine.class);
+ when(response.getStatusLine()).thenReturn(statusLine);
+ when(statusLine.getStatusCode()).thenReturn(200);
- HttpClientManager manager = mock(HttpClientManager.class);
- doReturn(builder).when(manager).createBuilder();
+ int statusCode = httpTransform.requestStatusCode(response);
- CloseableHttpClient client = mock(CloseableHttpClient.class);
- doReturn(client).when(builder).build();
+ assertEquals(200, statusCode);
+ }
+ @Test
+ void testSearchForHeaders() {
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
- doReturn(response)
- .when(client)
- .execute(any(HttpHost.class), any(HttpRequest.class),
any(HttpContext.class));
+ Header[] headers =
+ new Header[] {
+ new BasicHeader("Content-Type", "application/json"),
+ new BasicHeader("Authorization", "Bearer token")
+ };
+ when(response.getAllHeaders()).thenReturn(headers);
+
+ Header[] result = httpTransform.searchForHeaders(response);
+
+ assertNotNull(result);
+ assertEquals(2, result.length);
+ assertEquals("Content-Type", result[0].getName());
+ assertEquals("application/json", result[0].getValue());
+ }
+
+ @Test
+ void testCallHttpServiceBasicCall() throws Exception {
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("id"));
+ Object[] inputRow = new Object[] {"123"};
+
+ // Configure meta
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("result");
+ httpMeta.allocate(0, 0);
+
+ // Set up data
+ httpData.realUrl = TEST_URL;
+ httpData.realConnectionTimeout = 10000;
+ httpData.realSocketTimeout = 10000;
+ httpData.argnrs = new int[0];
+ httpData.inputRowMeta = inputRowMeta;
+ httpData.useHeaderParameters = false;
+ httpData.headerParametersNrs = new int[0];
+
+ // Mock HttpClientManager
+ try (MockedStatic<HttpClientManager> mockedManager =
mockStatic(HttpClientManager.class)) {
+ HttpClientManager mockManager = mock(HttpClientManager.class);
+ HttpClientManager.HttpClientBuilderFacade mockBuilder =
+ mock(HttpClientManager.HttpClientBuilderFacade.class);
+ CloseableHttpClient mockClient = mock(CloseableHttpClient.class);
+ CloseableHttpResponse mockResponse = mock(CloseableHttpResponse.class);
+
+
mockedManager.when(HttpClientManager::getInstance).thenReturn(mockManager);
+ when(mockManager.createBuilder()).thenReturn(mockBuilder);
+ doReturn(mockBuilder).when(mockBuilder).setConnectionTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setSocketTimeout(anyInt());
+ doReturn(mockBuilder).when(mockBuilder).setCredentials(anyString(),
anyString());
+ doReturn(mockBuilder).when(mockBuilder).setProxy(anyString(), anyInt());
+ // ignoreSsl is a void method, use doNothing
+
org.mockito.Mockito.doNothing().when(mockBuilder).ignoreSsl(anyBoolean());
+ when(mockBuilder.build()).thenReturn(mockClient);
+
+ // Mock HTTP response
+ StatusLine mockStatusLine = mock(StatusLine.class);
+
when(mockStatusLine.getStatusCode()).thenReturn(HttpURLConnection.HTTP_OK);
+ when(mockResponse.getStatusLine()).thenReturn(mockStatusLine);
+
+ HttpEntity mockEntity = mock(HttpEntity.class);
+ when(mockEntity.getContent())
+ .thenReturn(
+ new
ByteArrayInputStream(TEST_RESPONSE_BODY.getBytes(StandardCharsets.UTF_8)));
+ when(mockResponse.getEntity()).thenReturn(mockEntity);
+ when(mockResponse.getAllHeaders()).thenReturn(new Header[0]);
+
+ when(mockClient.execute(any(HttpHost.class), any(HttpRequest.class),
any(HttpContext.class)))
+ .thenReturn(mockResponse);
+
+ // Call the method
+ Object[] result = httpTransform.callHttpService(inputRowMeta, inputRow);
+
+ // Verify result
+ assertNotNull(result, "Result should not be null");
+ // Result should have input + response field (method adds response body
to end)
+ assertTrue(result.length >= 2, "Result should have at least input +
response fields");
+ assertEquals("123", result[0], "First field should be input ID");
+ assertEquals(TEST_RESPONSE_BODY, result[1], "Second field should be
response body");
+ }
+ }
+
+ @Test
+ void testCallHttpServiceWithResponseFields() throws Exception {
+ // Test that callHttpService prepares to return all response fields
+
+ // Configure meta with all response fields
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("responseBody");
+ httpMeta.setResultCodeFieldName("statusCode");
+ httpMeta.setResponseTimeFieldName("responseTime");
+ httpMeta.setResponseHeaderFieldName("responseHeaders");
+ httpMeta.allocate(0, 0);
+
+ // Set up input row
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("id"));
+
+ // Prepare output row meta
+ IRowMeta outputRowMeta = inputRowMeta.clone();
+ httpMeta.getFields(outputRowMeta, "HTTP", null, null, httpTransform, null);
+
+ // Verify output fields are configured
+ assertEquals(5, outputRowMeta.size()); // 1 input + 4 output fields
+ assertNotNull(outputRowMeta.searchValueMeta("responseBody"));
+ assertNotNull(outputRowMeta.searchValueMeta("statusCode"));
+ assertNotNull(outputRowMeta.searchValueMeta("responseTime"));
+ assertNotNull(outputRowMeta.searchValueMeta("responseHeaders"));
+ }
+
+ @Test
+ void testCallHttpServiceWithQueryParameters() throws Exception {
+ // Test callHttpService setup with query parameters
+
+ // Configure with query parameters
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("result");
+ httpMeta.allocate(2, 0);
+ httpMeta.getArgumentField()[0] = "userId";
+ httpMeta.getArgumentField()[1] = "filter";
+ httpMeta.getArgumentParameter()[0] = "id";
+ httpMeta.getArgumentParameter()[1] = "filter";
- BasicHttpEntity entity = new BasicHttpEntity();
- entity.setContent(new ByteArrayInputStream(DATA.getBytes()));
- doReturn(entity).when(response).getEntity();
-
mockedHttpClientManager.when(HttpClientManager::getInstance).thenReturn(manager);
+ // Set up input row
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("userId"));
+ inputRowMeta.addValueMeta(new ValueMetaString("filter"));
+ Object[] inputRow = new Object[] {"user123", "active"};
- doReturn(false).when(meta).isUrlInField();
- doReturn("body").when(meta).getFieldName();
+ // Set up data for the call
+ httpData.realUrl = TEST_URL;
+ httpData.argnrs = new int[] {0, 1};
+ httpData.inputRowMeta = inputRowMeta;
- doReturn(false).when(log).isDetailed();
+ // Verify parameters are accessible for URL building
+ assertEquals("user123", inputRowMeta.getString(inputRow, 0));
+ assertEquals("active", inputRowMeta.getString(inputRow, 1));
+ assertEquals("id", httpMeta.getArgumentParameter()[0]);
+ assertEquals("filter", httpMeta.getArgumentParameter()[1]);
+ }
+
+ @Test
+ void testCallHttpServiceWithHeaders() throws Exception {
+ // Test callHttpService setup with custom headers
+
+ // Configure with custom headers
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.setFieldName("result");
+ httpMeta.allocate(0, 2);
+ httpMeta.getHeaderField()[0] = "tokenField";
+ httpMeta.getHeaderField()[1] = "contentTypeField";
+ httpMeta.getHeaderParameter()[0] = "Authorization";
+ httpMeta.getHeaderParameter()[1] = "Content-Type";
- doCallRealMethod().when(http).callHttpService(any(IRowMeta.class),
any(Object[].class));
- doReturn(HttpURLConnection.HTTP_OK)
- .when(http)
- .requestStatusCode(any(CloseableHttpResponse.class));
- doReturn(new
Header[0]).when(http).searchForHeaders(any(CloseableHttpResponse.class));
+ // Set up input row
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("tokenField"));
+ inputRowMeta.addValueMeta(new ValueMetaString("contentTypeField"));
+ Object[] inputRow = new Object[] {"Bearer token123", "application/json"};
+
+ // Set up data
+ httpData.realUrl = TEST_URL;
+ httpData.argnrs = new int[0];
+ httpData.inputRowMeta = inputRowMeta;
+ httpData.useHeaderParameters = true;
+ httpData.headerParametersNrs = new int[] {0, 1};
+
+ // Verify headers are accessible
+ assertEquals("Bearer token123", inputRowMeta.getString(inputRow, 0));
+ assertEquals("application/json", inputRowMeta.getString(inputRow, 1));
+ assertEquals("Authorization", httpMeta.getHeaderParameter()[0]);
+ assertEquals("Content-Type", httpMeta.getHeaderParameter()[1]);
}
- @BeforeAll
- static void setUpStaticMocks() {
- mockedHttpClientManager = mockStatic(HttpClientManager.class);
+ @Test
+ void testGetFieldsAddsOutputFields() throws Exception {
+ httpMeta.setFieldName("responseBody");
+ httpMeta.setResultCodeFieldName("statusCode");
+ httpMeta.setResponseTimeFieldName("responseTime");
+ httpMeta.setResponseHeaderFieldName("headers");
+
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("input1"));
+
+ httpMeta.getFields(inputRowMeta, "HTTP", null, null, httpTransform, null);
+
+ assertEquals(5, inputRowMeta.size(), "Should have 5 fields (1 input + 4
output)");
+ assertNotNull(inputRowMeta.searchValueMeta("responseBody"));
+ assertNotNull(inputRowMeta.searchValueMeta("statusCode"));
+ assertNotNull(inputRowMeta.searchValueMeta("responseTime"));
+ assertNotNull(inputRowMeta.searchValueMeta("headers"));
}
- @AfterAll
- static void tearDownStaticMocks() {
- mockedHttpClientManager.close();
+ @Test
+ void testProcessRowWithUrlInField() throws Exception {
+ // Configure meta to use URL from field
+ httpMeta.setUrlInField(true);
+ httpMeta.setUrlField("urlColumn");
+ httpMeta.setFieldName("result");
+ httpMeta.allocate(0, 0);
+
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("urlColumn"));
+
+ // Create row with URL value
+ Object[] inputRow = new Object[] {"http://example.com/test"};
+
+ // Create spy and mock getRow
+ Http httpSpy = spy(httpTransform);
+ doReturn(inputRow).doReturn(null).when(httpSpy).getRow();
+ doReturn(inputRowMeta).when(httpSpy).getInputRowMeta();
+
+ // Initialize
+ httpSpy.init();
+ httpSpy.setInputRowMeta(inputRowMeta);
+
+ // Note: Full execution would require mocking HTTP client
+ // This test verifies the URL field resolution logic
+ httpData.inputRowMeta = inputRowMeta;
+ httpData.indexOfUrlField = inputRowMeta.indexOfValue("urlColumn");
+
+ assertEquals(0, httpData.indexOfUrlField, "URL field index should be
found");
}
- @Disabled("This test needs to be reviewed")
@Test
- void callHttpServiceWithUTF8Encoding() throws Exception {
- doReturn("UTF-8").when(meta).getEncoding();
- assertEquals(DATA, http.callHttpService(rmi, new Object[] {0})[0]);
+ void testProcessRowWithArgumentFields() throws Exception {
+ // Configure meta with argument fields
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.allocate(2, 0);
+ httpMeta.getArgumentField()[0] = "param1";
+ httpMeta.getArgumentField()[1] = "param2";
+ httpMeta.getArgumentParameter()[0] = "key1";
+ httpMeta.getArgumentParameter()[1] = "key2";
+ httpMeta.setFieldName("result");
+
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("param1"));
+ inputRowMeta.addValueMeta(new ValueMetaString("param2"));
+
+ // Create row with parameter values
+ Object[] inputRow = new Object[] {"value1", "value2"};
+
+ // Create spy
+ Http httpSpy = spy(httpTransform);
+ doReturn(inputRow).doReturn(null).when(httpSpy).getRow();
+ doReturn(inputRowMeta).when(httpSpy).getInputRowMeta();
+
+ // Initialize
+ httpSpy.init();
+ httpSpy.setInputRowMeta(inputRowMeta);
+
+ // Set up data for first row processing
+ httpData.inputRowMeta = inputRowMeta;
+ httpData.argnrs = new int[2];
+ httpData.argnrs[0] = inputRowMeta.indexOfValue("param1");
+ httpData.argnrs[1] = inputRowMeta.indexOfValue("param2");
+
+ assertEquals(0, httpData.argnrs[0]);
+ assertEquals(1, httpData.argnrs[1]);
}
- @Disabled("This test needs to be reviewed")
@Test
- void callHttpServiceWithoutEncoding() throws Exception {
- doReturn(null).when(meta).getEncoding();
- assertNotEquals(DATA, http.callHttpService(rmi, new Object[] {0})[0]);
+ void testProcessRowWithHeaderFields() throws Exception {
+ // Configure meta with header fields
+ httpMeta.setUrl(TEST_URL);
+ httpMeta.allocate(0, 2);
+ httpMeta.getHeaderField()[0] = "authField";
+ httpMeta.getHeaderField()[1] = "contentTypeField";
+ httpMeta.getHeaderParameter()[0] = "Authorization";
+ httpMeta.getHeaderParameter()[1] = "Content-Type";
+ httpMeta.setFieldName("result");
+
+ // Set up input row meta
+ IRowMeta inputRowMeta = new RowMeta();
+ inputRowMeta.addValueMeta(new ValueMetaString("authField"));
+ inputRowMeta.addValueMeta(new ValueMetaString("contentTypeField"));
+
+ // Create row with header values
+ Object[] inputRow = new Object[] {"Bearer token", "application/json"};
+
+ // Create spy
+ Http httpSpy = spy(httpTransform);
+ doReturn(inputRow).doReturn(null).when(httpSpy).getRow();
+ doReturn(inputRowMeta).when(httpSpy).getInputRowMeta();
+
+ // Initialize
+ httpSpy.init();
+ httpSpy.setInputRowMeta(inputRowMeta);
+
+ // Set up data
+ httpData.inputRowMeta = inputRowMeta;
+ httpData.headerParametersNrs = new int[2];
+ httpData.headerParametersNrs[0] = inputRowMeta.indexOfValue("authField");
+ httpData.headerParametersNrs[1] =
inputRowMeta.indexOfValue("contentTypeField");
+
+ assertEquals(0, httpData.headerParametersNrs[0]);
+ assertEquals(1, httpData.headerParametersNrs[1]);
}
}