From 84a0902e88e0277b1494e8802ca34c0ff0b11d72 Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Fri, 13 Dec 2024 15:44:11 +0000 Subject: [PATCH] Tests and fixes for Precondition requests for resources that don't exist Code clean-up - reformatting --- .../catalina/servlets/DefaultServlet.java | 41 +++---- ...tServletRfc9110Section13Parameterized.java | 109 ++++++++++++++---- 2 files changed, 102 insertions(+), 48 deletions(-) diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java index 595c1e0e54e5..caaf0111fed9 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -804,6 +804,10 @@ protected void serveResource(HttpServletRequest request, HttpServletResponse res if (isError) { response.sendError(((Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE)).intValue()); } else { + // Need to check If headers before we return a 404 + if (!checkIfHeaders(request, response, resource)) { + return; + } response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("defaultServlet.missingResource", requestUri)); } @@ -2221,36 +2225,27 @@ protected boolean checkIfNoneMatch(HttpServletRequest request, HttpServletRespon // representation for the target resource. if (resourceETag != null) { conditionSatisfied = false; - } else { - conditionSatisfied = true; } break; } } else { - if (resourceETag == null) { - // None of the entity tag matches. - conditionSatisfied = true; - break; - } else { - // RFC 7232 requires weak comparison for If-None-Match headers - Boolean matched = EntityTag.compareEntityTag(new StringReader(headerValue), true, resourceETag); - if (matched == null) { - if (debug > 10) { - log("DefaultServlet.checkIfNoneMatch: Invalid header value [" + headerValue + "]"); - } - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return false; - } - if (matched.booleanValue()) { - // RFC9110: If the field value is a list of entity tags, the condition is false if one of the - // listed tags - // matches the entity tag of the selected representation. - conditionSatisfied = false; - break; + // RFC 7232 requires weak comparison for If-None-Match headers + Boolean matched = EntityTag.compareEntityTag(new StringReader(headerValue), true, resourceETag); + if (matched == null) { + if (debug > 10) { + log("DefaultServlet.checkIfNoneMatch: Invalid header value [" + headerValue + "]"); } + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return false; + } + if (matched.booleanValue()) { + // RFC9110: If the field value is a list of entity tags, the condition is false if one of the + // listed tags + // matches the entity tag of the selected representation. + conditionSatisfied = false; + break; } } - } if (headerValues.hasMoreElements()) { headerCount++; diff --git a/test/org/apache/catalina/servlets/TestDefaultServletRfc9110Section13Parameterized.java b/test/org/apache/catalina/servlets/TestDefaultServletRfc9110Section13Parameterized.java index 53be3c6bd0e6..5621ea5cee6c 100644 --- a/test/org/apache/catalina/servlets/TestDefaultServletRfc9110Section13Parameterized.java +++ b/test/org/apache/catalina/servlets/TestDefaultServletRfc9110Section13Parameterized.java @@ -152,6 +152,65 @@ public static Collection parameters() { null, Boolean.FALSE, SC_200 }); } + for (Task task : Arrays.asList(Task.HEAD_404_HTML, Task.GET_404_HTML, Task.POST_404_HTML)) { + // RFC 9110, Section 13.2.2, Step 1, HEAD: If-Match with and without If-Unmodified-Since + for (DatePrecondition dateCondition : DatePrecondition.values()) { + parameterSets.add(new Object[] { useStrongEtag, task, EtagPrecondition.ALL, dateCondition, null, + null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, task, EtagPrecondition.IN, dateCondition, null, + null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, task, EtagPrecondition.NOT_IN, dateCondition, null, + null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, task, EtagPrecondition.INVALID, dateCondition, null, + null, null, null, Boolean.FALSE, SC_400 }); + parameterSets.add(new Object[] { useStrongEtag, task, EtagPrecondition.INVALID_ALL_PLUS_OTHER, + dateCondition, null, null, null, null, Boolean.FALSE, SC_400 }); + } + + // RFC 9110, Section 13.2.2, Step 2, HEAD: If-Unmodified-Since only + parameterSets.add(new Object[] { useStrongEtag, task, null, DatePrecondition.EQ, null, null, null, null, + Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, DatePrecondition.LT, null, null, null, null, + Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, DatePrecondition.GT, null, null, null, null, + Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, DatePrecondition.MULTI_IN, null, null, null, + null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, DatePrecondition.MULTI_IN_REV, null, null, + null, null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, DatePrecondition.INVALID, null, null, null, + null, Boolean.FALSE, SC_404 }); + + // RFC 9110, Section 13.2.2, Step 3, HEAD: If-None-Match with and without If-Modified-Since + for (DatePrecondition dateCondition : DatePrecondition.values()) { + parameterSets.add(new Object[] { useStrongEtag, task, null, null, EtagPrecondition.ALL, + dateCondition, null, null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, EtagPrecondition.IN, + dateCondition, null, null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, EtagPrecondition.NOT_IN, + dateCondition, null, null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, EtagPrecondition.INVALID, + dateCondition, null, null, Boolean.FALSE, SC_400 }); + parameterSets.add( + new Object[] { useStrongEtag, task, null, null, EtagPrecondition.INVALID_ALL_PLUS_OTHER, + dateCondition, null, null, Boolean.FALSE, SC_400 }); + } + + // RFC 9110, Section 13.2.2, Step 4, HEAD: If-Modified-Since only + parameterSets.add(new Object[] { useStrongEtag, task, null, null, null, DatePrecondition.EQ, null, null, + Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, null, DatePrecondition.LT, null, null, + Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, null, DatePrecondition.GT, null, null, + Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, null, DatePrecondition.MULTI_IN, null, + null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, null, DatePrecondition.MULTI_IN_REV, + null, null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, task, null, null, null, DatePrecondition.INVALID, null, + null, Boolean.FALSE, SC_404 }); + } + // RFC 9110, Section 13.2.2, Step 5, GET: If-Range only // entity-tag parameterSets.add(new Object[] { useStrongEtag, Task.GET_INDEX_HTML, null, null, null, null, @@ -262,31 +321,31 @@ public static Collection parameters() { // DELETE TESTS parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, null, null, null, null, null, null, Boolean.FALSE, SC_204 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.ALL, null, null, null, null, null, - Boolean.FALSE, SC_204 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.EXACTLY, null, null, null, null, null, - Boolean.FALSE, useStrongEtag.booleanValue() ? SC_204 : SC_412 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.IN, null, null, null, null, null, - Boolean.FALSE, useStrongEtag.booleanValue() ? SC_204 : SC_412 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.NOT_IN, null, null, null, null, null, - Boolean.FALSE, SC_412 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.INVALID, null, null, null, null, null, - Boolean.FALSE, SC_400 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.INVALID_ALL_PLUS_OTHER, null, null, null, null, null, - Boolean.FALSE, SC_400 }); - - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, null, null, null, null, null, null, - Boolean.FALSE, SC_404 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.ALL, null, null, null, null, null, - Boolean.FALSE, SC_412 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.IN, null, null, null, null, null, - Boolean.FALSE, SC_412 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.NOT_IN, null, null, null, null, null, - Boolean.FALSE, SC_412 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.INVALID, null, null, null, null, null, - Boolean.FALSE, SC_400 }); - parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.INVALID_ALL_PLUS_OTHER, null, null, null, null, null, - Boolean.FALSE, SC_400 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.ALL, null, null, + null, null, null, Boolean.FALSE, SC_204 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.EXACTLY, null, null, + null, null, null, Boolean.FALSE, useStrongEtag.booleanValue() ? SC_204 : SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.IN, null, null, + null, null, null, Boolean.FALSE, useStrongEtag.booleanValue() ? SC_204 : SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.NOT_IN, null, null, + null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, EtagPrecondition.INVALID, null, null, + null, null, null, Boolean.FALSE, SC_400 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_EXIST_TXT, + EtagPrecondition.INVALID_ALL_PLUS_OTHER, null, null, null, null, null, Boolean.FALSE, SC_400 }); + + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, null, null, null, null, null, + null, Boolean.FALSE, SC_404 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.ALL, null, null, + null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.IN, null, null, + null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.NOT_IN, null, + null, null, null, null, Boolean.FALSE, SC_412 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, EtagPrecondition.INVALID, null, + null, null, null, null, Boolean.FALSE, SC_400 }); + parameterSets.add(new Object[] { useStrongEtag, Task.DELETE_NOT_EXIST_TXT, + EtagPrecondition.INVALID_ALL_PLUS_OTHER, null, null, null, null, null, Boolean.FALSE, SC_400 }); } return parameterSets;