diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-http/pom.xml b/dolphinscheduler-task-plugin/dolphinscheduler-task-http/pom.xml
index 1e58ced1af..015d3193e0 100644
--- a/dolphinscheduler-task-plugin/dolphinscheduler-task-http/pom.xml
+++ b/dolphinscheduler-task-plugin/dolphinscheduler-task-http/pom.xml
@@ -15,19 +15,18 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
+ 4.0.0
- dolphinscheduler-task-plugin
org.apache.dolphinscheduler
+ dolphinscheduler-task-plugin
dev-SNAPSHOT
- 4.0.0
-
+
dolphinscheduler-task-http
jar
-
+
org.apache.dolphinscheduler
@@ -39,7 +38,7 @@
dolphinscheduler-task-api
${project.version}
-
+
org.apache.commons
commons-collections4
@@ -52,6 +51,17 @@
org.apache.httpcomponents
httpcore
-
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ test
+
+
+ junit
+ junit
+
+
+
diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-http/src/test/java/org/apache/dolphinscheduler/plugin/task/http/HttpTaskTest.java b/dolphinscheduler-task-plugin/dolphinscheduler-task-http/src/test/java/org/apache/dolphinscheduler/plugin/task/http/HttpTaskTest.java
new file mode 100644
index 0000000000..23b8095f83
--- /dev/null
+++ b/dolphinscheduler-task-plugin/dolphinscheduler-task-http/src/test/java/org/apache/dolphinscheduler/plugin/task/http/HttpTaskTest.java
@@ -0,0 +1,270 @@
+/*
+ * 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.dolphinscheduler.plugin.task.http;
+
+import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.EXIT_CODE_FAILURE;
+import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.EXIT_CODE_SUCCESS;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext;
+import org.apache.dolphinscheduler.plugin.task.api.model.Property;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpStatus;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import okhttp3.HttpUrl;
+import okhttp3.mockwebserver.Dispatcher;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import okhttp3.mockwebserver.RecordedRequest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Test HttpTask
+ */
+public class HttpTaskTest {
+
+ private static final String CONTENT_TYPE = "Content-Type";
+
+ private static final String APPLICATION_JSON_VALUE = "application/json";
+
+ private static final String MOCK_DISPATCH_PATH_REQ_BODY_TO_RES_BODY = "/requestBody/to/responseBody";
+
+ private static final String MOCK_DISPATCH_PATH_REQ_PARAMS_TO_RES_BODY = "/requestParams/to/responseBody";
+
+ private final List mockWebServers = new ArrayList<>();
+
+ @After
+ public void after() {
+ mockWebServers.forEach(IOUtils::closeQuietly);
+ mockWebServers.clear();
+ }
+
+ @Test
+ public void testHandleCheckCodeDefaultSuccess() throws Exception {
+ HttpTask getHttpTask = generateHttpTask(HttpMethod.GET, HttpStatus.SC_OK);
+ HttpTask postHttpTask = generateHttpTask(HttpMethod.POST, HttpStatus.SC_OK);
+ HttpTask headHttpTask = generateHttpTask(HttpMethod.HEAD, HttpStatus.SC_OK);
+ HttpTask putHttpTask = generateHttpTask(HttpMethod.PUT, HttpStatus.SC_OK);
+ HttpTask deleteHttpTask = generateHttpTask(HttpMethod.DELETE, HttpStatus.SC_OK);
+ getHttpTask.handle();
+ postHttpTask.handle();
+ headHttpTask.handle();
+ putHttpTask.handle();
+ deleteHttpTask.handle();
+ Assert.assertEquals(EXIT_CODE_SUCCESS, getHttpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_SUCCESS, postHttpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_SUCCESS, headHttpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_SUCCESS, putHttpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_SUCCESS, deleteHttpTask.getExitStatusCode());
+ }
+
+ @Test
+ public void testHandleCheckCodeDefaultError() throws Exception {
+ HttpTask getHttpTask = generateHttpTask(HttpMethod.GET, HttpStatus.SC_BAD_REQUEST);
+ getHttpTask.handle();
+ Assert.assertEquals(EXIT_CODE_FAILURE, getHttpTask.getExitStatusCode());
+ }
+
+ @Test
+ public void testHandleCheckCodeCustom() throws Exception {
+ String condition = HttpStatus.SC_CREATED + "";
+ HttpTask httpTask = generateHttpTask(HttpMethod.GET, HttpCheckCondition.STATUS_CODE_CUSTOM,
+ condition, HttpStatus.SC_CREATED, "");
+ HttpTask httpErrorTask = generateHttpTask(HttpMethod.GET, HttpCheckCondition.STATUS_CODE_CUSTOM,
+ condition, HttpStatus.SC_OK, "");
+ httpTask.handle();
+ httpErrorTask.handle();
+ Assert.assertEquals(EXIT_CODE_SUCCESS, httpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_FAILURE, httpErrorTask.getExitStatusCode());
+ }
+
+ @Test
+ public void testHandleCheckBodyContains() throws Exception {
+ HttpTask httpTask = generateHttpTask(HttpMethod.GET, HttpCheckCondition.BODY_CONTAINS,
+ "success", HttpStatus.SC_OK, "{\"status\": \"success\"}");
+ HttpTask httpErrorTask = generateHttpTask(HttpMethod.GET, HttpCheckCondition.BODY_CONTAINS,
+ "success", HttpStatus.SC_OK, "{\"status\": \"failed\"}");
+ httpTask.handle();
+ httpErrorTask.handle();
+ Assert.assertEquals(EXIT_CODE_SUCCESS, httpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_FAILURE, httpErrorTask.getExitStatusCode());
+ }
+
+ @Test
+ public void testHandleCheckBodyNotContains() throws Exception {
+ HttpTask httpTask = generateHttpTask(HttpMethod.GET, HttpCheckCondition.BODY_NOT_CONTAINS,
+ "failed", HttpStatus.SC_OK, "{\"status\": \"success\"}");
+ HttpTask httpErrorTask = generateHttpTask(HttpMethod.GET, HttpCheckCondition.BODY_NOT_CONTAINS,
+ "failed", HttpStatus.SC_OK, "{\"status\": \"failed\"}");
+ httpTask.handle();
+ httpErrorTask.handle();
+ Assert.assertEquals(EXIT_CODE_SUCCESS, httpTask.getExitStatusCode());
+ Assert.assertEquals(EXIT_CODE_FAILURE, httpErrorTask.getExitStatusCode());
+ }
+
+ @Test
+ public void testHandleWithHttpBodyParams() throws Exception {
+ List httpParams = new ArrayList<>();
+ HttpProperty property = new HttpProperty();
+ property.setProp("day");
+ property.setValue("${day}");
+ property.setHttpParametersType(HttpParametersType.BODY);
+ httpParams.add(property);
+
+ Map prepareParamsMap = new HashMap<>();
+ prepareParamsMap.put("day", "20220812");
+ // The MockWebServer will return the request body as response body directly
+ // So we just need to check if the response body contains string "20220812"
+ HttpTask httpTask = generateHttpTask(MOCK_DISPATCH_PATH_REQ_BODY_TO_RES_BODY, HttpMethod.POST,
+ httpParams, prepareParamsMap, HttpCheckCondition.BODY_CONTAINS, "20220812",
+ HttpStatus.SC_OK, "");
+ httpTask.handle();
+ Assert.assertEquals(EXIT_CODE_SUCCESS, httpTask.getExitStatusCode());
+ }
+
+ @Test
+ public void testHandleWithHttpParameterParams() throws Exception {
+ List httpParams = new ArrayList<>();
+ HttpProperty property = new HttpProperty();
+ property.setProp("day");
+ property.setValue("${day}");
+ property.setHttpParametersType(HttpParametersType.PARAMETER);
+ httpParams.add(property);
+
+ Map prepareParamsMap = new HashMap<>();
+ prepareParamsMap.put("day", "20220812");
+ // The MockWebServer will return the request parameter as response body directly
+ // So we just need to check if the response body contains string "20220812"
+ HttpTask httpTask = generateHttpTask(MOCK_DISPATCH_PATH_REQ_PARAMS_TO_RES_BODY, HttpMethod.POST,
+ httpParams, prepareParamsMap, HttpCheckCondition.BODY_CONTAINS, "20220812",
+ HttpStatus.SC_OK, "");
+ httpTask.handle();
+ Assert.assertEquals(EXIT_CODE_SUCCESS, httpTask.getExitStatusCode());
+ }
+
+ private String withMockWebServer(String path, int actualResponseCode,
+ String actualResponseBody) throws IOException {
+ MockWebServer server = new MockWebServer();
+ mockWebServers.add(server);
+ server.start();
+ server.setDispatcher(generateMockDispatcher(path, actualResponseCode, actualResponseBody));
+ return server.url(path).toString();
+ }
+
+ private HttpTask generateHttpTask(HttpMethod httpMethod, int actualResponseCode) throws IOException {
+ return generateHttpTask("/test", httpMethod, null, null,
+ HttpCheckCondition.STATUS_CODE_DEFAULT, "", actualResponseCode, "");
+ }
+
+ private HttpTask generateHttpTask(HttpMethod httpMethod, HttpCheckCondition httpCheckConditionType,
+ String condition, int actualResponseCode,
+ String actualResponseBody) throws IOException {
+ return generateHttpTask("/test", httpMethod, null, null,
+ httpCheckConditionType, condition, actualResponseCode, actualResponseBody);
+ }
+ private HttpTask generateHttpTask(String mockPath, HttpMethod httpMethod, List httpParams,
+ Map prepareParamsMap, HttpCheckCondition httpCheckConditionType,
+ String condition, int actualResponseCode,
+ String actualResponseBody) throws IOException {
+ String url = withMockWebServer(mockPath, actualResponseCode, actualResponseBody);
+ String paramData = generateHttpParameters(url, httpMethod, httpParams, httpCheckConditionType, condition);
+ return generateHttpTaskFromParamData(paramData, prepareParamsMap);
+ }
+
+ private HttpTask generateHttpTaskFromParamData(String paramData, Map prepareParamsMap) {
+ TaskExecutionContext taskExecutionContext = Mockito.mock(TaskExecutionContext.class);
+ when(taskExecutionContext.getTaskParams()).thenReturn(paramData);
+ if (prepareParamsMap != null) {
+ Map propertyParamsMap = new HashMap<>();
+ prepareParamsMap.forEach((k, v) -> {
+ Property property = new Property();
+ property.setProp(k);
+ property.setValue(v);
+ propertyParamsMap.put(k, property);
+ });
+ when(taskExecutionContext.getPrepareParamsMap()).thenReturn(propertyParamsMap);
+ }
+ HttpTask httpTask = new HttpTask(taskExecutionContext);
+ httpTask.init();
+ return httpTask;
+ }
+
+ private String generateHttpParameters(String url, HttpMethod httpMethod, List httpParams,
+ HttpCheckCondition httpCheckConditionType,
+ String condition) throws JsonProcessingException {
+ ObjectMapper mapper = new ObjectMapper();
+ HttpParameters httpParameters = new HttpParameters();
+ httpParameters.setUrl(url);
+ httpParameters.setHttpMethod(httpMethod);
+ httpParameters.setHttpCheckCondition(httpCheckConditionType);
+ httpParameters.setCondition(condition);
+ httpParameters.setConnectTimeout(10000);
+ httpParameters.setSocketTimeout(10000);
+ httpParameters.setHttpParams(httpParams);
+ return mapper.writeValueAsString(httpParameters);
+ }
+
+ private Dispatcher generateMockDispatcher(String path, int actualResponseCode, String actualResponseBody) {
+ return new Dispatcher() {
+
+ @Override
+ public MockResponse dispatch(RecordedRequest request) {
+ MockResponse mockResponse = new MockResponse()
+ .setResponseCode(actualResponseCode)
+ .setHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE);
+
+ if (request.getPath().startsWith(MOCK_DISPATCH_PATH_REQ_BODY_TO_RES_BODY)) {
+ // return request body as mock response body
+ mockResponse.setBody(request.getBody().readUtf8());
+ } else if (request.getPath().startsWith(MOCK_DISPATCH_PATH_REQ_PARAMS_TO_RES_BODY)) {
+ // return request params as mock response body
+ ObjectMapper mapper = new ObjectMapper();
+ HttpUrl httpUrl = request.getRequestUrl();
+ Set parameterNames = httpUrl.queryParameterNames();
+ Map resBodyMap = new HashMap<>();
+ parameterNames.forEach(name -> resBodyMap.put(name, httpUrl.queryParameter(name)));
+ try {
+ mockResponse.setBody(mapper.writeValueAsString(resBodyMap));
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ } else if (request.getPath().startsWith(path)) {
+ mockResponse.setBody(actualResponseBody);
+ } else {
+ mockResponse.setResponseCode(HttpStatus.SC_NOT_FOUND);
+ }
+ return mockResponse;
+ }
+ };
+ }
+}