Merge pull request #1206 from apache/AMQ-9841

AMQ-9481 - Correctly complete async servlet request on timeout
This commit is contained in:
Christopher L. Shannon 2024-04-22 11:01:35 -04:00 committed by GitHub
commit 6e6caf7c60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 8 deletions

View File

@ -86,11 +86,20 @@ public class RestTest extends JettyTestSupport {
HttpClient httpClient = new HttpClient(); HttpClient httpClient = new HttpClient();
httpClient.start(); httpClient.start();
final StringBuffer buf = new StringBuffer(); // AMQ-9330 - test no 500 error on timeout and instead 204 error
final Future<Result> result = Future<Result> result =
asyncRequest(httpClient, "http://localhost:" + port + "/message/test?readTimeout=1000&type=queue", buf); asyncRequest(httpClient, "http://localhost:" + port + "/message/test?readTimeout=2000&type=queue&clientId=test", new StringBuffer());
// try a second request while the first is running, this should get a 500 error since the first is still running and
// concurrent access to the same consumer is not allowed
Future<Result> errorResult = asyncRequest(httpClient, "http://localhost:" + port + "/message/test?readTimeout=1&type=queue&clientId=test", new StringBuffer());
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, errorResult.get().getResponse().getStatus());
//After the original request finishes, verify 204 and not 500 error
assertEquals(HttpStatus.NO_CONTENT_204, result.get().getResponse().getStatus());
//Test timeout, no message was sent // AMQ-9481 - test to make sure we can re-use the consumer after timeout by trying again and ensuring
// no 500 error. Before the fix in AMQ-9418 this would fail even after the previous request timed out
result =
asyncRequest(httpClient, "http://localhost:" + port + "/message/test?readTimeout=1000&type=queue&clientId=test", new StringBuffer());
assertEquals(HttpStatus.NO_CONTENT_204, result.get().getResponse().getStatus()); assertEquals(HttpStatus.NO_CONTENT_204, result.get().getResponse().getStatus());
} }

View File

@ -115,10 +115,10 @@ public class AsyncServletRequest implements AsyncListener {
} }
final AsyncContext context = event.getAsyncContext(); final AsyncContext context = event.getAsyncContext();
if (context != null) { if (context != null && event.getSuppliedRequest().isAsyncStarted()) {
// We must call complete and then set the status code to prevent a 500 // We must call dispatch to finish the request on timeout.
// error. The spec requires a 500 error on timeout unless complete() is called. // then set the status code to prevent a 500 error.
context.complete(); context.dispatch();
final ServletResponse response = context.getResponse(); final ServletResponse response = context.getResponse();
if (response instanceof HttpServletResponse) { if (response instanceof HttpServletResponse) {
((HttpServletResponse) response).setStatus(HttpServletResponse.SC_NO_CONTENT); ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_NO_CONTENT);