I'm using Tomcat 8.5.9. It appears that query strings containing percent encoded ampersand (%26) and percent (%25) characters are not parsed correctly when using the HTTP/2 connector. Using HTTP 1.1, it works fine. To reproduce: 1) create ROOT/test.jsp with these contents: foo=[<%= request.getParameter("foo") %>] 2) Set up an HTTPS connector in server.xml that upgrades to HTTP/2 and start the server: <Connector port="8443" scheme="https" secure="true" SSLEnabled="true" compression="on" address="0.0.0.0"> <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig protocols="TLSv1.1+TLSv1.2"> <Certificate certificateKeyFile="conf\tls\key.pem" certificateFile="conf\cert.crt" certificateChainFile="conf\tls\STAR_credentialsmart_net.ca-bundle" /> </SSLHostConfig> </Connector> 3) Browse to https://localhost:8443/test.jsp?foo=b%26a The result is: foo=[b] 4) Now comment out <UpgradeProtocol ...> in the HTTPS connector in server.xml and restart. 5) Browse to https://localhost:8443/test.jsp?foo=b%26a The result is: foo=[b&a] The access log also shows the URLs differently: 0:0:0:0:0:0:0:1 - - [15/Dec/2016:02:12:22 -0500] "GET /test.jsp?foo=b%26a HTTP/1.1" 200 14 0:0:0:0:0:0:0:1 - - [15/Dec/2016:02:12:36 -0500] "GET /test.jsp?foo=b&a HTTP/2.0" 200 12 And the logs show the message: 14-Dec-2016 23:48:59.846 FINE [catalina-exec-2] org.apache.tomcat.util.http.Parameters.processParameters Parameter starting at position [10] and ending at position [15] with a value of [10] was not followed by an = character
I don't really understand the reason of the URL decoding here: https://github.com/apache/tomcat/blob/trunk/java/org/apache/coyote/http2/Stream.java#L264 Most likely Parameters always has to do the decoding since we still live with these query string encoding configuration options.
Other than me not thinking straight, I don't see a reason for that decoding either. Query string decoding has to be deferred to parameter parsing so that encoding of reserved characters - such as '&' - is handled correctly. Should be a simple fix.
Tests pass, and I added a test case. This will be in 9M16 and 8.5.10.