From 39e44bf2ae35c54e80d28431cb182296768c7641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B5=E7=AB=8B=E4=BD=B3?= <418843795@qq.com> Date: Mon, 21 Apr 2025 10:38:28 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=86=85=E7=BD=AEhttp=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=99=A8=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E7=BB=93=E6=9E=9C=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/config/SnailJobProperties.java | 23 +++++ .../builtin/AbstractHttpExecutor.java | 97 +++++++++++++++++-- 2 files changed, 112 insertions(+), 8 deletions(-) diff --git a/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java b/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java index 5f7bfe02d..6da5e17b5 100644 --- a/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java +++ b/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java @@ -70,6 +70,11 @@ public class SnailJobProperties { */ private ServerConfig server = new ServerConfig(); + /** + * 内置http执行器自定义响应结果配置 + */ + private HttpResponse httpResponse = new HttpResponse(); + /** * 重试模块配置 */ @@ -109,6 +114,24 @@ public class SnailJobProperties { private int port = 17888; } + @Data + public static class HttpResponse { + /** + * 内置http执行器响应成功状态码,默认值200 + */ + private int code; + + /** + * 内置http执行器状态码字段名称,默认值code,只针对responseType等于json生效 + */ + private String field; + + /** + * 内置http执行器响应类型,可选值json或者text,默认值json + */ + private String responseType; + } + @Data public static class SlidingWindowConfig { diff --git a/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java b/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java index 24e406d2a..fc5b4d9b7 100644 --- a/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java +++ b/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java @@ -14,6 +14,7 @@ import org.springframework.util.StringUtils; import java.util.Base64; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.regex.Pattern; @@ -55,14 +56,7 @@ public abstract class AbstractHttpExecutor { private ExecuteResult executeRequestAndHandleResponse(HttpRequest httpRequest) { try (HttpResponse response = httpRequest.execute()) { - int errCode = response.getStatus(); - String body = response.body(); - if (errCode != HTTP_SUCCESS_CODE) { - SnailJobLog.LOCAL.error("{} request to URL: {} failed with code: {}, response body: {}", - httpRequest.getMethod(), httpRequest.getUrl(), errCode, body); - return ExecuteResult.failure("HTTP request failed"); - } - return ExecuteResult.success(body); + return validateResponse(response, httpRequest, snailJobProperties.getHttpResponse()); } catch (Exception e) { throw new SnailJobInnerExecutorException("[snail-job] HTTP internal executor failed", e); } @@ -75,6 +69,93 @@ public abstract class AbstractHttpExecutor { httpParams.setUrl(httpParams.getUrl().startsWith(HTTP) ? httpParams.getUrl() : HTTP_PREFIX + httpParams.getUrl()); } + /** + * 验证http响应是否有效,并根据响应类型进行进一步验证 + * + * @param response + * @param httpRequest + * @param httpResponse + * @return + */ + private ExecuteResult validateResponse(HttpResponse response, HttpRequest httpRequest, SnailJobProperties.HttpResponse httpResponse) { + int errCode = response.getStatus(); + String body = response.body(); + // 检查http响应状态码是否为成功状态码 + if (errCode != HTTP_SUCCESS_CODE) { + SnailJobLog.LOCAL.error("{} request to URL: {} failed with code: {}, response body: {}", + httpRequest.getMethod(), httpRequest.getUrl(), errCode, body); + return ExecuteResult.failure("HTTP request failed"); + } + // 如果配置了httpResponse,则根据响应类型进行进一步验证 + if (Objects.nonNull(httpResponse)) { + int code = Optional.of(httpResponse.getCode()).orElse(HTTP_SUCCESS_CODE); + String field = Optional.of(httpResponse.getField()).orElse("code"); + String responseType = Optional.of(httpResponse.getResponseType()).orElse("json"); + // 根据不同的响应类型进行验证 + if ("json".equalsIgnoreCase(responseType)) { + return validateJsonResponse(body, code, field, httpRequest); + } else if ("text".equalsIgnoreCase(responseType)) { + return validateTextResponse(body, code, httpRequest); + } else { + return ExecuteResult.failure("the responseType is not json or text"); + } + } + return ExecuteResult.success(body); + } + + /** + * 验证json响应类型 + * + * @param body + * @param code + * @param field + * @param httpRequest + * @return + */ + private ExecuteResult validateJsonResponse(String body, int code, String field, HttpRequest httpRequest) { + // 检查响应体是否为json格式 + if (!JsonUtil.isValidJson(body) || JsonUtil.isEmptyJson(body)) { + SnailJobLog.LOCAL.error("the responseType is json,but the response body fails to validate json or json is empty"); + return ExecuteResult.failure("the responseType is json,but the response body fails to validate json or json is empty"); + } + // 检查响应体是否包含指定的状态码字段 + Map objectObjectMap = JsonUtil.parseHashMap(body); + if (!objectObjectMap.containsKey(field)) { + SnailJobLog.LOCAL.error("the responseType is json,but there is no status code field:" + field); + return ExecuteResult.failure("the responseType is json,but there is no status code field:" + field); + } + // 检查响应体中状态码是否与指定的状态码是否一致 + if (!Objects.equals(code, objectObjectMap.get(field))) { + SnailJobLog.LOCAL.error("{} request to URL: {} failed with code: {}, response body: {}", + httpRequest.getMethod(), httpRequest.getUrl(), code, body); + return ExecuteResult.failure("the response status code is not equal to the specified status code"); + } + return ExecuteResult.success(body); + } + + /** + * 验证text响应类型 + * + * @param body + * @param code + * @param httpRequest + * @return + */ + private ExecuteResult validateTextResponse(String body, int code, HttpRequest httpRequest) { + // 检查响应体是否为空 + if (!StringUtils.hasLength(body)) { + SnailJobLog.LOCAL.error("the responseType is text,but the response body is empty"); + return ExecuteResult.failure("the responseType is text,but the response body is empty"); + } + // 检查响应体是否与指定的状态码是否一致 + if (!Objects.equals(code + "", body)) { + SnailJobLog.LOCAL.error("{} request to URL: {} failed with code: {}, response body: {}", + httpRequest.getMethod(), httpRequest.getUrl(), code, body); + return ExecuteResult.failure("the response status code is not equal to the specified status code"); + } + return ExecuteResult.success(body); + } + private void setDefaultMethodAndBody(HttpParams httpParams) { if (StringUtils.isEmpty(httpParams.getMethod())) { httpParams.setMethod(DEFAULT_REQUEST_METHOD); From fbf69987628a586eb275edd744f42a222b42058e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B5=E7=AB=8B=E4=BD=B3?= <418843795@qq.com> Date: Mon, 21 Apr 2025 15:44:25 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=86=85=E7=BD=AEhttp=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=99=A8=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E7=BB=93=E6=9E=9C=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/common/config/SnailJobProperties.java | 8 ++++---- .../core/executor/builtin/AbstractHttpExecutor.java | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java b/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java index 6da5e17b5..ca0492155 100644 --- a/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java +++ b/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java @@ -73,7 +73,7 @@ public class SnailJobProperties { /** * 内置http执行器自定义响应结果配置 */ - private HttpResponse httpResponse = new HttpResponse(); + private HttpResponse httpResponse; /** * 重试模块配置 @@ -119,17 +119,17 @@ public class SnailJobProperties { /** * 内置http执行器响应成功状态码,默认值200 */ - private int code; + private int code = 200; /** * 内置http执行器状态码字段名称,默认值code,只针对responseType等于json生效 */ - private String field; + private String field = "code"; /** * 内置http执行器响应类型,可选值json或者text,默认值json */ - private String responseType; + private String responseType = "json"; } @Data diff --git a/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java b/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java index fc5b4d9b7..63f00e29d 100644 --- a/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java +++ b/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java @@ -30,6 +30,8 @@ public abstract class AbstractHttpExecutor { private static final String HTTP_PREFIX = "http://"; private static final int HTTP_SUCCESS_CODE = 200; private static final Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]"); + private static final String JSON_RESPONSE_TYPE = "json"; + private static final String TEXT_RESPONSE_TYPE = "text"; public ExecuteResult process(HttpParams httpParams) { if (httpParams == null) { @@ -88,13 +90,13 @@ public abstract class AbstractHttpExecutor { } // 如果配置了httpResponse,则根据响应类型进行进一步验证 if (Objects.nonNull(httpResponse)) { - int code = Optional.of(httpResponse.getCode()).orElse(HTTP_SUCCESS_CODE); - String field = Optional.of(httpResponse.getField()).orElse("code"); - String responseType = Optional.of(httpResponse.getResponseType()).orElse("json"); + int code = httpResponse.getCode(); + String field = httpResponse.getField(); + String responseType = httpResponse.getResponseType(); // 根据不同的响应类型进行验证 - if ("json".equalsIgnoreCase(responseType)) { + if (JSON_RESPONSE_TYPE.equalsIgnoreCase(responseType)) { return validateJsonResponse(body, code, field, httpRequest); - } else if ("text".equalsIgnoreCase(responseType)) { + } else if (TEXT_RESPONSE_TYPE.equalsIgnoreCase(responseType)) { return validateTextResponse(body, code, httpRequest); } else { return ExecuteResult.failure("the responseType is not json or text"); From 3ac7a5b3123bfcee928599e67debb5a3726f3e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B5=E7=AB=8B=E4=BD=B3?= <418843795@qq.com> Date: Mon, 21 Apr 2025 17:24:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=86=85=E7=BD=AEhttp=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=99=A8=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E7=BB=93=E6=9E=9C=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/common/config/SnailJobProperties.java | 2 +- .../executor/builtin/AbstractHttpExecutor.java | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java b/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java index ca0492155..565cad932 100644 --- a/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java +++ b/snail-job-client/snail-job-client-common/src/main/java/com/aizuda/snailjob/client/common/config/SnailJobProperties.java @@ -119,7 +119,7 @@ public class SnailJobProperties { /** * 内置http执行器响应成功状态码,默认值200 */ - private int code = 200; + private Integer code = 200; /** * 内置http执行器状态码字段名称,默认值code,只针对responseType等于json生效 diff --git a/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java b/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java index 63f00e29d..46a734020 100644 --- a/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java +++ b/snail-job-client/snail-job-client-job-core/src/main/java/com/aizuda/snailjob/client/job/core/executor/builtin/AbstractHttpExecutor.java @@ -30,9 +30,10 @@ public abstract class AbstractHttpExecutor { private static final String HTTP_PREFIX = "http://"; private static final int HTTP_SUCCESS_CODE = 200; private static final Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]"); + private static final int RESPONSE_SUCCESS_CODE = 200; + private static final String RESPONSE_CODE_FIELD = "code"; private static final String JSON_RESPONSE_TYPE = "json"; private static final String TEXT_RESPONSE_TYPE = "text"; - public ExecuteResult process(HttpParams httpParams) { if (httpParams == null) { String message = "HttpParams is null. Verify jobParam configuration."; @@ -90,9 +91,14 @@ public abstract class AbstractHttpExecutor { } // 如果配置了httpResponse,则根据响应类型进行进一步验证 if (Objects.nonNull(httpResponse)) { - int code = httpResponse.getCode(); - String field = httpResponse.getField(); - String responseType = httpResponse.getResponseType(); + // 防止显示声明字段但是未配置值 + int code = Optional.ofNullable(httpResponse.getCode()).orElse(RESPONSE_SUCCESS_CODE); + String field = Optional.ofNullable(httpResponse.getField()) + .filter(StringUtils::hasLength) + .orElse(RESPONSE_CODE_FIELD); + String responseType = Optional.ofNullable(httpResponse.getField()) + .filter(StringUtils::hasLength) + .orElse(JSON_RESPONSE_TYPE); // 根据不同的响应类型进行验证 if (JSON_RESPONSE_TYPE.equalsIgnoreCase(responseType)) { return validateJsonResponse(body, code, field, httpRequest);