diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/util/ServletUtils.java b/continew-starter-core/src/main/java/top/continew/starter/core/util/ServletUtils.java index 48ff14bb..227861d5 100644 --- a/continew-starter-core/src/main/java/top/continew/starter/core/util/ServletUtils.java +++ b/continew-starter-core/src/main/java/top/continew/starter/core/util/ServletUtils.java @@ -18,6 +18,7 @@ package top.continew.starter.core.util; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.JakartaServletUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; @@ -189,5 +190,38 @@ public class ServletUtils extends JakartaServletUtil { write(response, data, MediaType.APPLICATION_JSON_VALUE); } + /** + * 检查请求是否为 {@code multipart/form-data} 格式(常用于文件上传) + * + * @param request 请求对象 + * @return true: 是; false: 否 + * @since 2.15.1 + */ + public static boolean isMultipart(HttpServletRequest request) { + return StrUtil.startWithIgnoreCase(request.getContentType(), "multipart/"); + } + /** + * 检查 HTTP 请求是否为 {@code application/x-www-form-urlencoded} 格式(标准表单提交) + * + * @param request 请求对象 + * @return true: 是; false: 否 + * @see MediaType#APPLICATION_FORM_URLENCODED_VALUE + * @since 2.15.1 + */ + public static boolean isForm(HttpServletRequest request) { + return StrUtil.contains(request.getContentType(), MediaType.APPLICATION_FORM_URLENCODED_VALUE); + } + + /** + * 检查 HTTP 响应是否为 {@code Server-Sent Events (SSE)} 流格式 + * + * @param response 响应对象 + * @return true: 是; false: 否 + * @see MediaType#TEXT_EVENT_STREAM_VALUE + * @since 2.15.1 + */ + public static boolean isStream(HttpServletResponse response) { + return StrUtil.contains(response.getContentType(), MediaType.TEXT_EVENT_STREAM_VALUE); + } } diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadRequestWrapper.java b/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadRequestWrapper.java index bc2180b8..588b66ee 100644 --- a/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadRequestWrapper.java +++ b/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadRequestWrapper.java @@ -18,13 +18,12 @@ package top.continew.starter.core.wrapper; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; -import jakarta.servlet.ServletRequest; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; -import org.springframework.http.MediaType; import org.springframework.util.FastByteArrayOutputStream; import org.springframework.util.StreamUtils; import top.continew.starter.core.constant.StringConstants; +import top.continew.starter.core.util.ServletUtils; import java.io.*; import java.net.URLEncoder; @@ -77,8 +76,8 @@ public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { ? new FastByteArrayOutputStream(contentLength) : new FastByteArrayOutputStream(); // 判断是否为文件上传请求 - if (!isMultipartContent(request)) { - if (isFormRequest()) { + if (!ServletUtils.isMultipart(request)) { + if (ServletUtils.isForm(request)) { writeRequestParametersToCachedContent(); } else { StreamUtils.copy(request.getInputStream(), cachedContent); @@ -90,7 +89,7 @@ public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { @Override public ServletInputStream getInputStream() throws IOException { // 如果是文件上传,直接返回原始输入流 - if (isMultipartContent(super.getRequest())) { + if (ServletUtils.isMultipart((HttpServletRequest)super.getRequest())) { return super.getRequest().getInputStream(); } synchronized (this) { @@ -102,7 +101,7 @@ public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { @Override public BufferedReader getReader() throws IOException { // 如果是文件上传,直接返回原始Reader - if (isMultipartContent(super.getRequest())) { + if (ServletUtils.isMultipart((HttpServletRequest)super.getRequest())) { return super.getRequest().getReader(); } @@ -153,22 +152,6 @@ public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { return cachedContent; } - /** - * 判断当前请求是否为 multipart/form-data 类型的文件上传请求。 该类型一般用于表单上传文件的场景,例如 enctype="multipart/form-data"。 - * - * @param request 当前 HTTP 请求对象 - * @return true 表示为 multipart 文件上传请求;否则为 false - */ - public boolean isMultipartContent(ServletRequest request) { - String contentType = request.getContentType(); - return contentType != null && contentType.toLowerCase().startsWith("multipart/"); - } - - private boolean isFormRequest() { - String contentType = getContentType(); - return (contentType != null && contentType.contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE)); - } - /** * Body 缓存的ServletInputStream实现 DefaultServerRequestBuilder.BodyInputStream */ diff --git a/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadResponseWrapper.java b/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadResponseWrapper.java index 33b065c8..83323a44 100644 --- a/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadResponseWrapper.java +++ b/continew-starter-core/src/main/java/top/continew/starter/core/wrapper/RepeatReadResponseWrapper.java @@ -20,7 +20,7 @@ import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; -import org.springframework.http.MediaType; +import top.continew.starter.core.util.ServletUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -46,30 +46,11 @@ public class RepeatReadResponseWrapper extends HttpServletResponseWrapper { public RepeatReadResponseWrapper(HttpServletResponse response) { super(response); - checkStreamingResponse(); - } - - @Override - public void setContentType(String type) { - super.setContentType(type); - // 根据 Content-Type 判断是否为流式响应 - if (type != null) { - String lowerType = type.toLowerCase(); - isStreamingResponse = lowerType.contains(MediaType.TEXT_EVENT_STREAM_VALUE); - } - } - - private void checkStreamingResponse() { - String contentType = getContentType(); - if (contentType != null) { - String lowerType = contentType.toLowerCase(); - isStreamingResponse = lowerType.contains(MediaType.TEXT_EVENT_STREAM_VALUE); - } + isStreamingResponse = ServletUtils.isStream(response); } @Override public ServletOutputStream getOutputStream() throws IOException { - checkStreamingResponse(); // 对于 SSE 流式响应,直接返回原始响应流,不做额外处理 if (isStreamingResponse) { return super.getOutputStream(); @@ -103,7 +84,6 @@ public class RepeatReadResponseWrapper extends HttpServletResponseWrapper { @Override public PrintWriter getWriter() throws IOException { - checkStreamingResponse(); if (isStreamingResponse) { // 对于 SSE 流式响应,直接返回原始响应写入器,不做额外处理 return super.getWriter(); diff --git a/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/http/servlet/RecordableServletHttpRequest.java b/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/http/servlet/RecordableServletHttpRequest.java index 45bddf8c..d8b98cb7 100644 --- a/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/http/servlet/RecordableServletHttpRequest.java +++ b/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/http/servlet/RecordableServletHttpRequest.java @@ -17,12 +17,12 @@ package top.continew.starter.log.http.servlet; import cn.hutool.core.text.CharSequenceUtil; -import cn.hutool.extra.servlet.JakartaServletUtil; import cn.hutool.json.JSONUtil; import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.util.UriUtils; import org.springframework.web.util.WebUtils; import top.continew.starter.core.constant.StringConstants; +import top.continew.starter.core.util.ServletUtils; import top.continew.starter.core.wrapper.RepeatReadRequestWrapper; import top.continew.starter.log.http.RecordableHttpRequest; @@ -75,7 +75,7 @@ public final class RecordableServletHttpRequest implements RecordableHttpRequest @Override public Map getHeaders() { - return JakartaServletUtil.getHeaderMap(request); + return ServletUtils.getHeaderMap(request); } @Override @@ -83,7 +83,7 @@ public final class RecordableServletHttpRequest implements RecordableHttpRequest try { RepeatReadRequestWrapper wrappedRequest = WebUtils .getNativeRequest(request, RepeatReadRequestWrapper.class); - if (wrappedRequest == null || wrappedRequest.isMultipartContent(request)) { + if (wrappedRequest == null || ServletUtils.isMultipart(request)) { return null; } String body = wrappedRequest.getContentAsString(); @@ -96,12 +96,12 @@ public final class RecordableServletHttpRequest implements RecordableHttpRequest @Override public String getParams() { String body = this.getBody(); - return CharSequenceUtil.isNotBlank(body) ? body : JSONUtil.toJsonStr(JakartaServletUtil.getParamMap(request)); + return CharSequenceUtil.isNotBlank(body) ? body : JSONUtil.toJsonStr(ServletUtils.getParamMap(request)); } @Override public String getIp() { - return JakartaServletUtil.getClientIP(request); + return ServletUtils.getClientIP(request); } /**