[
https://issues.apache.org/jira/browse/CXF-8936?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Andriy Redko updated CXF-8936:
------------------------------
Fix Version/s: (was: 3.5.8)
> 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)