diff --git a/conf/server.xml b/conf/server.xml index 1be01d58594b..7df34e0038eb 100644 --- a/conf/server.xml +++ b/conf/server.xml @@ -160,6 +160,9 @@ resourceName="UserDatabase"/> + + + diff --git a/java/org/apache/catalina/valves/LowerCaseHeadersValve.java b/java/org/apache/catalina/valves/LowerCaseHeadersValve.java new file mode 100644 index 000000000000..dcc41a447604 --- /dev/null +++ b/java/org/apache/catalina/valves/LowerCaseHeadersValve.java @@ -0,0 +1,57 @@ +package org.apache.catalina.valves; + +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.MimeHeaders; + +import javax.servlet.ServletException; +import java.io.IOException; +import java.util.*; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + +public class LowerCaseHeadersValve extends ValveBase { + private static final Log log = LogFactory.getLog(LowerCaseHeadersValve.class); + + @Override + public void invoke(org.apache.catalina.connector.Request request, Response response) throws IOException, ServletException { + log.debug("in"); + // Access the Coyote request (Tomcat's internal request object) + org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest(); + MimeHeaders mimeHeaders = coyoteRequest.getMimeHeaders(); + + // Preserve original header names with case + Map> originalHeaders = new LinkedHashMap<>(); + + for (int i = 0; i < mimeHeaders.size(); i++) { + MessageBytes nameMessageBytes = mimeHeaders.getName(i); + MessageBytes valueMessageBytes = mimeHeaders.getValue(i); + + String name = nameMessageBytes.toString(); + String value = valueMessageBytes.toString(); + + if(log.isDebugEnabled()) { + log.debug("raw: "+name+": "+value); + } + + originalHeaders.computeIfAbsent(name, k -> new ArrayList<>()).add(value); + + nameMessageBytes.setString(name.toLowerCase()); + + if(log.isDebugEnabled()) { + name = nameMessageBytes.toString(); + value = valueMessageBytes.toString(); + log.debug("current: "+name+": "+value); + } + } + + // Store headers in request attributes for downstream use + request.setAttribute("originalHeaders", originalHeaders); + + // Continue pipeline + getNext().invoke(request, response); + } +} + diff --git a/java/org/apache/coyote/http11/Http11InputBuffer.java b/java/org/apache/coyote/http11/Http11InputBuffer.java index 9903301011a3..66eab7d781e4 100644 --- a/java/org/apache/coyote/http11/Http11InputBuffer.java +++ b/java/org/apache/coyote/http11/Http11InputBuffer.java @@ -906,11 +906,6 @@ private HeaderParseStatus parseHeader() throws IOException { // skipLine() will handle the error return skipLine(false); } - - // chr is next byte of header name. Convert to lowercase. - if (chr >= Constants.A && chr <= Constants.Z) { - byteBuffer.put(pos, (byte) (chr - Constants.LC_OFFSET)); - } } // Skip the line and ignore the header