Index: java/org/apache/catalina/connector/Request.java =================================================================== --- java/org/apache/catalina/connector/Request.java (revision 831702) +++ java/org/apache/catalina/connector/Request.java (working copy) @@ -29,9 +29,11 @@ import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.TimeZone; import java.util.TreeMap; @@ -94,11 +96,24 @@ // ----------------------------------------------------------- Constructors + private static final Set internalAttributeNames = + new HashSet(); + private static final Set sslAttributeNames = new HashSet(); static { // Ensure that classes are loaded for SM new StringCache.ByteEntry(); new StringCache.CharEntry(); + + // Populate the lists of internal attribute names + internalAttributeNames.add(Globals.DISPATCHER_TYPE_ATTR); + internalAttributeNames.add(Globals.DISPATCHER_REQUEST_PATH_ATTR); + internalAttributeNames.add(Globals.ASYNC_SUPPORTED_ATTR); + sslAttributeNames.add(Globals.CERTIFICATES_ATTR); + sslAttributeNames.add(Globals.CIPHER_SUITE_ATTR); + sslAttributeNames.add(Globals.KEY_SIZE_ATTR); + sslAttributeNames.add(Globals.SSL_SESSION_ID_ATTR); + sslAttributeNames.add(Globals.SSL_SESSION_MGR_ATTR); } public Request() { @@ -922,10 +937,14 @@ * empty Enumeration if there are none. */ public Enumeration getAttributeNames() { + Set names = new HashSet(); + names.addAll(attributes.keySet()); + names.addAll(internalAttributeNames); + names.addAll(coyoteRequest.getAttributes().keySet()); if (isSecure()) { - getAttribute(Globals.CERTIFICATES_ATTR); + names.addAll(sslAttributeNames); } - return new Enumerator(attributes.keySet(), true); + return new Enumerator(names, false); } Index: test/org/apache/catalina/connector/TestRequest.java =================================================================== --- test/org/apache/catalina/connector/TestRequest.java (revision 831702) +++ test/org/apache/catalina/connector/TestRequest.java (working copy) @@ -191,4 +191,65 @@ } } + + /** + * Test case for https://issues.apache.org/bugzilla/show_bug.cgi?id=47364. + * Responses to request.getAttributeNames() do not include the internal + * Tomcat attributes + */ + public void testBug47364() throws Exception { + Bug47364Client client = new Bug47364Client(); + client.doRequest(); + assertTrue(client.isResponseBodyOK()); + } + + private static class Bug47364Servlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + PrintWriter out = resp.getWriter(); + Enumeration names = req.getAttributeNames(); + while (names.hasMoreElements()) { + out.println(names.nextElement()); + } + } + + } + + private class Bug47364Client extends SimpleHttpClient { + + private void doRequest() throws Exception { + Tomcat tomcat = getTomcatInstance(); + Connector connector = + new Connector("org.apache.coyote.http11.Http11NioProtocol"); + connector.setPort(getNextPort()); + tomcat.getService().addConnector(connector); + + StandardContext root = tomcat.addContext("", TEMP_DIR); + Tomcat.addServlet(root, "Bug47364", new Bug47364Servlet()); + root.addServletMapping("/test", "Bug47364"); + tomcat.start(); + + setPort(connector.getPort()); + + String[] request = new String[1]; + request[0] = "GET /test HTTP/1.0" + CRLF + CRLF; + connect(); + setRequest(request); + processRequest(); // blocks until response has been read + + // Close the connection + disconnect(); + } + + @Override + public boolean isResponseBodyOK() { + return getResponseBody().contains( + "org.apache.tomcat.sendfile.support"); + } + + } }