Skip to content

Commit ac88a60

Browse files
committed
Ensure error is sent before Writer or OutputStream is used
Previously, ErrorPageFilter's ErrorResponseWrapper would delaying sending an error back to the client. In cases where the response's Writer or OutputStream was accessed and flushed or closed, this could lead to the wrong response status being sent. This commit updates ErrorResponseWrapper so that it will send any capture error to the client before returning the response's Writer or OutputStream. This ensures that closing the Writer or OutputStream does not cause the response to be committed with the default response status rather than the previously captured error status. Such responses will now include the correct status, but will not be forwarded to the error controller. Such forwarding is not possible due to the response already having been committed. Closes gh-11814
1 parent 1805cc5 commit ac88a60

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
package org.springframework.boot.web.support;
1818

1919
import java.io.IOException;
20+
import java.io.PrintWriter;
2021
import java.util.HashMap;
2122
import java.util.Map;
2223

2324
import javax.servlet.Filter;
2425
import javax.servlet.FilterChain;
2526
import javax.servlet.FilterConfig;
2627
import javax.servlet.ServletException;
28+
import javax.servlet.ServletOutputStream;
2729
import javax.servlet.ServletRequest;
2830
import javax.servlet.ServletResponse;
2931
import javax.servlet.http.HttpServletRequest;
@@ -311,11 +313,15 @@ public int getStatus() {
311313

312314
@Override
313315
public void flushBuffer() throws IOException {
316+
sendErrorIfNecessary();
317+
super.flushBuffer();
318+
}
319+
320+
private void sendErrorIfNecessary() throws IOException {
314321
if (this.hasErrorToSend && !isCommitted()) {
315322
((HttpServletResponse) getResponse()).sendError(this.status,
316323
this.message);
317324
}
318-
super.flushBuffer();
319325
}
320326

321327
public String getMessage() {
@@ -326,6 +332,19 @@ public boolean hasErrorToSend() {
326332
return this.hasErrorToSend;
327333
}
328334

335+
@Override
336+
public PrintWriter getWriter() throws IOException {
337+
sendErrorIfNecessary();
338+
return super.getWriter();
339+
340+
}
341+
342+
@Override
343+
public ServletOutputStream getOutputStream() throws IOException {
344+
sendErrorIfNecessary();
345+
return super.getOutputStream();
346+
}
347+
329348
}
330349

331350
}

spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterTests.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -521,6 +521,22 @@ public void doFilter(ServletRequest request, ServletResponse response)
521521
assertThat(this.response.getForwardedUrl()).isEqualTo("/500");
522522
}
523523

524+
@Test
525+
public void whenErrorIsSentAndWriterIsFlushedErrorIsSentToTheClient()
526+
throws Exception {
527+
this.chain = new MockFilterChain() {
528+
@Override
529+
public void doFilter(ServletRequest request, ServletResponse response)
530+
throws IOException, ServletException {
531+
((HttpServletResponse) response).sendError(400);
532+
response.getWriter().flush();
533+
super.doFilter(request, response);
534+
}
535+
};
536+
this.filter.doFilter(this.request, this.response, this.chain);
537+
assertThat(this.response.getStatus()).isEqualTo(400);
538+
}
539+
524540
private void setUpAsyncDispatch() throws Exception {
525541
this.request.setAsyncSupported(true);
526542
this.request.setAsyncStarted(true);

0 commit comments

Comments
 (0)