Skip to content

Commit d30d3e3

Browse files
committed
Providing the error does not require the immediate closure of the connection, pass all errors (invalid requests etc.) that occur before the request processing pipeline is reached to the standard error handling mechanism so that the application error handling or the ErrorReportVlave can handle it.
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.5.x/trunk@1853174 13f79535-47bb-0310-9956-ffa450edef68
1 parent 0c7fddc commit d30d3e3

File tree

8 files changed

+39
-22
lines changed

8 files changed

+39
-22
lines changed

java/org/apache/catalina/connector/CoyoteAdapter.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,14 +393,25 @@ public void service(org.apache.coyote.Request req, org.apache.coyote.Response re
393393
// Log only if processing was invoked.
394394
// If postParseRequest() failed, it has already logged it.
395395
Context context = request.getContext();
396+
Host host = request.getHost();
396397
// If the context is null, it is likely that the endpoint was
397398
// shutdown, this connection closed and the request recycled in
398399
// a different thread. That thread will have updated the access
399400
// log so it is OK not to update the access log here in that
400401
// case.
402+
// The other possibility is that an error occurred early in
403+
// processing and the request could not be mapped to a Context.
404+
// Log via the host or engine in that case.
405+
long time = System.currentTimeMillis() - req.getStartTime();
401406
if (context != null) {
402-
context.logAccess(request, response,
403-
System.currentTimeMillis() - req.getStartTime(), false);
407+
context.logAccess(request, response, time, false);
408+
} else if (response.isError()) {
409+
if (host != null) {
410+
host.logAccess(request, response, time, false);
411+
} else {
412+
connector.getService().getContainer().logAccess(
413+
request, response, time, false);
414+
}
404415
}
405416
}
406417

java/org/apache/coyote/AbstractProcessor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ protected AbstractProcessor(AbstractEndpoint<?> endpoint, Request coyoteRequest,
100100
* @param t The error which occurred
101101
*/
102102
protected void setErrorState(ErrorState errorState, Throwable t) {
103+
response.setError();
103104
boolean blockIo = this.errorState.isIoAllowed() && !errorState.isIoAllowed();
104105
this.errorState = this.errorState.getMostSevere(errorState);
105106
// Don't change the status code for IOException since that is almost

java/org/apache/coyote/Response.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ public int getStatus() {
224224
* @param status The status value to set
225225
*/
226226
public void setStatus(int status) {
227+
if (this.status > 399) {
228+
// Don't overwrite first recorded error status
229+
return;
230+
}
227231
this.status = status;
228232
}
229233

java/org/apache/coyote/ajp/AjpProcessor.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,9 @@ public SocketState service(SocketWrapperBase<?> socket) throws IOException {
446446
// 400 - Bad Request
447447
response.setStatus(400);
448448
setErrorState(ErrorState.CLOSE_CLEAN, t);
449-
getAdapter().log(request, response, 0);
450449
}
451450

452-
if (!getErrorState().isError()) {
451+
if (getErrorState().isIoAllowed()) {
453452
// Setting up filters, and parse some request headers
454453
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
455454
try {
@@ -460,20 +459,18 @@ public SocketState service(SocketWrapperBase<?> socket) throws IOException {
460459
// 500 - Internal Server Error
461460
response.setStatus(500);
462461
setErrorState(ErrorState.CLOSE_CLEAN, t);
463-
getAdapter().log(request, response, 0);
464462
}
465463
}
466464

467-
if (!getErrorState().isError() && !cping && endpoint.isPaused()) {
465+
if (getErrorState().isIoAllowed() && !cping && endpoint.isPaused()) {
468466
// 503 - Service unavailable
469467
response.setStatus(503);
470468
setErrorState(ErrorState.CLOSE_CLEAN, null);
471-
getAdapter().log(request, response, 0);
472469
}
473470
cping = false;
474471

475472
// Process the request in the adapter
476-
if (!getErrorState().isError()) {
473+
if (getErrorState().isIoAllowed()) {
477474
try {
478475
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
479476
getAdapter().service(request, response);
@@ -933,7 +930,7 @@ private void prepareRequest() {
933930
MessageBytes valueMB = request.getMimeHeaders().getValue("host");
934931
parseHost(valueMB);
935932

936-
if (getErrorState().isError()) {
933+
if (!getErrorState().isIoAllowed()) {
937934
getAdapter().log(request, response, 0);
938935
}
939936
}

java/org/apache/coyote/http11/Http11Processor.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,6 @@ public SocketState service(SocketWrapperBase<?> socketWrapper)
733733
// 400 - Bad Request
734734
response.setStatus(400);
735735
setErrorState(ErrorState.CLOSE_CLEAN, t);
736-
getAdapter().log(request, response, 0);
737736
}
738737

739738
// Has an upgrade been requested?
@@ -769,7 +768,7 @@ public SocketState service(SocketWrapperBase<?> socketWrapper)
769768
}
770769
}
771770

772-
if (!getErrorState().isError()) {
771+
if (getErrorState().isIoAllowed()) {
773772
// Setting up filters, and parse some request headers
774773
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
775774
try {
@@ -782,7 +781,6 @@ public SocketState service(SocketWrapperBase<?> socketWrapper)
782781
// 500 - Internal Server Error
783782
response.setStatus(500);
784783
setErrorState(ErrorState.CLOSE_CLEAN, t);
785-
getAdapter().log(request, response, 0);
786784
}
787785
}
788786

@@ -794,7 +792,7 @@ public SocketState service(SocketWrapperBase<?> socketWrapper)
794792
}
795793

796794
// Process the request in the adapter
797-
if (!getErrorState().isError()) {
795+
if (getErrorState().isIoAllowed()) {
798796
try {
799797
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
800798
getAdapter().service(request, response);
@@ -920,7 +918,6 @@ private boolean handleIncompleteRequestLineRead() {
920918
// Partially processed the request so need to respond
921919
response.setStatus(503);
922920
setErrorState(ErrorState.CLOSE_CLEAN, null);
923-
getAdapter().log(request, response, 0);
924921
return false;
925922
} else {
926923
// Need to keep processor associated with socket
@@ -1210,7 +1207,7 @@ private void prepareRequest() {
12101207
contentDelimitation = true;
12111208
}
12121209

1213-
if (getErrorState().isError()) {
1210+
if (!getErrorState().isIoAllowed()) {
12141211
getAdapter().log(request, response, 0);
12151212
}
12161213
}

test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,8 @@ public void testSecret() throws Exception {
512512
TesterAjpMessage responseHeaders = ajpClient.sendMessage(forwardMessage);
513513
// Expect 3 packets: headers, body, end
514514
validateResponseHeaders(responseHeaders, 403, "403");
515-
//TesterAjpMessage responseBody = ajpClient.readMessage();
516-
//validateResponseBody(responseBody, HelloWorldServlet.RESPONSE_TEXT);
515+
TesterAjpMessage responseBody = ajpClient.readMessage();
516+
validateResponseBody(responseBody, "<p><b>Type</b> Status Report</p>");
517517
validateResponseEnd(ajpClient.readMessage(), false);
518518

519519
ajpClient.connect();
@@ -526,8 +526,8 @@ public void testSecret() throws Exception {
526526
responseHeaders = ajpClient.sendMessage(forwardMessage);
527527
// Expect 3 packets: headers, body, end
528528
validateResponseHeaders(responseHeaders, 403, "403");
529-
//responseBody = ajpClient.readMessage();
530-
//validateResponseBody(responseBody, HelloWorldServlet.RESPONSE_TEXT);
529+
responseBody = ajpClient.readMessage();
530+
validateResponseBody(responseBody, "<p><b>Type</b> Status Report</p>");
531531
validateResponseEnd(ajpClient.readMessage(), false);
532532

533533
ajpClient.connect();
@@ -540,7 +540,7 @@ public void testSecret() throws Exception {
540540
responseHeaders = ajpClient.sendMessage(forwardMessage);
541541
// Expect 3 packets: headers, body, end
542542
validateResponseHeaders(responseHeaders, 200, "200");
543-
TesterAjpMessage responseBody = ajpClient.readMessage();
543+
responseBody = ajpClient.readMessage();
544544
validateResponseBody(responseBody, HelloWorldServlet.RESPONSE_TEXT);
545545
validateResponseEnd(ajpClient.readMessage(), true);
546546

@@ -641,7 +641,9 @@ public void doTestPost(boolean multipleCL, int expectedStatus,
641641
// Double check the connection is still open
642642
validateCpong(ajpClient.cping());
643643
} else {
644-
// Expect 2 messages: headers, end for an invalid request
644+
// Expect 3 messages: headers, error report body, end for an invalid request
645+
TesterAjpMessage responseBody = ajpClient.readMessage();
646+
validateResponseBody(responseBody, "<p><b>Type</b> Status Report</p>");
645647
validateResponseEnd(ajpClient.readMessage(), false);
646648
}
647649

test/org/apache/tomcat/util/http/TestMimeHeadersIntegration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ private void runHeadersTest(final boolean successExpected,
9494
client.getResponseLine() != null && client.isResponse200());
9595
Assert.assertEquals("OK", client.getResponseBody());
9696
} else {
97-
alv.validateAccessLog(1, 400, 0, 0);
97+
alv.validateAccessLog(1, 400, 0, 3000);
9898
// Connection aborted or response 400
9999
Assert.assertTrue("Response line is: " + client.getResponseLine(),
100100
client.getResponseLine() == null || client.isResponse400());

webapps/docs/changelog.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@
7070
Pass 400 errors triggered by invalid request targets to the container
7171
error handling to generate the response body. (markt)
7272
</add>
73+
<add>
74+
Pass errors triggered by invalid requests or unavailable services to the
75+
application provided error handling and/or the container provided error
76+
handling (<code>ErrorReportValve</code>) as appropriate. (markt)
77+
</add>
7378
</changelog>
7479
</subsection>
7580
<subsection name="WebSocket">

0 commit comments

Comments
 (0)