[ https://issues.apache.org/jira/browse/CXF-8936?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Andriy Redko resolved CXF-8936. ------------------------------- Resolution: Fixed > Fix h2 protocol negotiation in Jetty Transport > ---------------------------------------------- > > Key: CXF-8936 > URL: https://issues.apache.org/jira/browse/CXF-8936 > Project: CXF > Issue Type: Bug > Components: Transports > Affects Versions: 4.0.3 > Environment: CXF latest and CXF 4.0.3 on Java 11 and 17 both show > this issue. > Reporter: Huw Ayling-Miller > Priority: Minor > Labels: Jetty > Fix For: 3.6.3, 4.0.4 > > Attachments: output-jetty-original.txt, output-netty.txt > > > h1. Summary > I have been trying to update one of our apps using the Jetty backend to use > http2. While doing this I've noticed that the protocol negotiation is in the > wrong order which results in http/1.1 always being preferred where the client > includes this in the ALPN handshake. This means that both browsers and cURL > will never successfully negotiate h2/http2. > --- > h1. The problem > The issue can be shown using curl. > {{curl -ikv https://localhost:9000}} > I've attached the full output of this command when running curl against the > CXF sample {{jax_rs_basic_http2_jetty}}. > The important lines are: > {code} > * ALPN: offers h2,http/1.1 > * ALPN: server accepted http/1.1 > {code} > Compare this with the attached curl output from the CXF sample > {{jax_rs_basic_http2_netty}}. > The important lines here are: > {code} > * ALPN: offers h2,http/1.1 > * ALPN: server accepted h2 > {code} > --- > h1. The solution > The ALPN takes place within {{ALPNServerConnection}}, which is part of the > {{jetty-alpn-server}} module. > {code:java} > // RFC 7301 states that the server picks the protocol > // that it prefers that is also supported by the client. > for (String serverProtocol : serverProtocols) > { > if (clientProtocols.contains(serverProtocol)) > { > ConnectionFactory factory = > getConnector().getConnectionFactory(serverProtocol); > if (factory instanceof CipherDiscriminator && > !((CipherDiscriminator)factory).isAcceptable(serverProtocol, tlsProtocol, > tlsCipher)) > { > if (LOG.isDebugEnabled()) > LOG.debug("Protocol {} not acceptable to {} for {}/{} > on {}", serverProtocol, factory, tlsProtocol, tlsCipher, getEndPoint()); > continue; > } > negotiated = serverProtocol; > break; > } > } > {code} > As the code states, the server is responsible for picking the protocol and > Jetty picks the first match in the server's list. From the log output of the > same app the first in the list is http/1.1 > {code} > INFO: Started ServerConnector@11eadcba\{ssl, (http/1.1, ssl, alpn, > h2)}{0.0.0.0:9000}} > {code} > Therefore the solution is to ensure that when h2 is enabled inside > {{JettyHTTPServerEngine}} -> {{createConnectorJetty}}, the > HTTP2ServerConnectionFactory should always be added at the start of the list. > With this change, curl then successfully negotiates with h2. -- This message was sent by Atlassian Jira (v8.20.10#820010)