Skip to content

ContentCachingResponseWrapper is not returning servlet response to the client #34325

@Kowalik94

Description

@Kowalik94
org.springframework.boot spring-boot-starter-parent 2.7.13

ContentCachingResponseWrapper
DeferredResult
OpenJDK 1.8.0_202

Filter:

 @Component
 @Order(Ordered.HIGHEST_PRECEDENCE)
  public class ContentCachingFilter extends OncePerRequestFilter {
    private static final Logger logger = LoggerFactory.getLogger(ContentCachingFilter.class);
    public static final String REST_UUID = "X-request-id";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

        if (request.getHeader(REST_UUID) == null) {
            String uuid = UUID.randomUUID().toString();
            request.setAttribute(REST_UUID, uuid);
            response.setHeader(REST_UUID, uuid);
        } else {
            String headerParam = request.getHeader(REST_UUID);
            request.setAttribute(REST_UUID, headerParam);
            response.setHeader(REST_UUID, headerParam);
        }

        logger.info("Before ContentCachingFilter");

        filterChain.doFilter(request, responseWrapper);

        logger.info("After ContentCachingFilter");
        responseWrapper.copyBodyToResponse();


    }
}

Servlet:

@Slf4j
@RestController
@RequestMapping("/servlet")
public class MyServlet {

	int counter = 1;
	
	@PostMapping("/deferred")
        DeferredResult<ResponseEntity<Object>> doDeferred(HttpServletRequest request,  @RequestBody String requestBody) throws InterruptedException {
        final ResponseEntity<Object> timeoutResponse = ResponseEntity.status(503).body("Deferred timeout");
        final DeferredResult<ResponseEntity<Object>> responseEntityDeferredResult = new DeferredResult<ResponseEntity<Object>>(6000L,timeoutResponse);

        if(requestBody == null){
            requestBody = "anything";
        }
        final String finalRequestBody = requestBody;
		counter++;
		System.out.println(counter);
        if(finalRequestBody.contains("sleep")){
            ForkJoinPool.commonPool().submit(() -> {
                log.info("Processing in separate thread");
                if(finalRequestBody.equals("sleepMore")){
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {

                    }
                } else {
                    try {
                        Thread.sleep(4000);
                    } catch (InterruptedException e) {

                    }
                }

                log.info("After the sleep execution");
                responseEntityDeferredResult.setResult(ResponseEntity.status(200).body("Deferred successfully returned"));
                log.info("Finished processing in separate thread");
            });
        } else {
            responseEntityDeferredResult.setResult(ResponseEntity.status(200).body("Deferred successfully returned"));
        }

        return responseEntityDeferredResult;
    }

}

Result of service:

C:\Users\XXX\Desktop\CURL>curl -H "Content-Type:text/plain" --trace-time http://localhost:18080/servlet/deferred -d
sleep -v
13:16:39.266200 * Host localhost:18080 was resolved.
13:16:39.275872 * IPv6: ::1
13:16:39.278151 * IPv4: 127.0.0.1
13:16:39.286604 *   Trying [::1]:18080...
13:16:39.291555 * Connected to localhost (::1) port 18080
13:16:39.295087 > POST /servlet/deferred HTTP/1.1
13:16:39.295087 > Host: localhost:18080
13:16:39.295087 > User-Agent: curl/8.9.1
13:16:39.295087 > Accept: */*
13:16:39.295087 > Content-Type:text/plain
13:16:39.295087 > Content-Length: 5
13:16:39.295087 >
13:16:39.314630 * upload completely sent off: 5 bytes
13:16:43.443178 < HTTP/1.1 200
13:16:43.445868 < X-request-id: faec4178-3dc7-4e5f-a5bc-55d7ff46629a
13:16:43.449375 < Content-Type: text/plain;charset=UTF-8
13:16:43.452905 < Content-Length: 30
13:16:43.454768 < Date: Mon, 27 Jan 2025 12:16:44 GMT
13:16:43.458651 <
13:17:44.198648 * end of response with 30 bytes missing
13:17:44.203690 * closing connection #0
curl: (18) end of response with 30 bytes missing

Expected result of service when HttpServletResponse object used instead of ContentCachingResponseWrapper object:

C:\Users\XXX\Desktop\CURL>curl -H "Content-Type:text/plain" --trace-time http://localhost:18080/servlet/deferred -d sleep -v
13:32:24.414975 * Host localhost:18080 was resolved.
13:32:24.423820 * IPv6: ::1
13:32:24.426342 * IPv4: 127.0.0.1
13:32:24.434983 *   Trying [::1]:18080...
13:32:24.439253 * Connected to localhost (::1) port 18080
13:32:24.443102 > POST /servlet/deferred HTTP/1.1
13:32:24.443102 > Host: localhost:18080
13:32:24.443102 > User-Agent: curl/8.9.1
13:32:24.443102 > Accept: */*
13:32:24.443102 > Content-Type:text/plain
13:32:24.443102 > Content-Length: 5
13:32:24.443102 >
13:32:24.462354 * upload completely sent off: 5 bytes
13:32:28.591708 < HTTP/1.1 200
13:32:28.594241 < X-request-id: a7d2adef-1155-4903-8b11-bc4836af7c32
13:32:28.597334 < Content-Type: text/plain;charset=UTF-8
13:32:28.600276 < Content-Length: 30
13:32:28.602554 < Date: Mon, 27 Jan 2025 12:32:28 GMT
13:32:28.605220 <
Deferred successfully returned13:32:28.606942 * Connection #0 to host localhost left intact

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: stackoverflowA question that's better suited to stackoverflow.comstatus: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions