HTTP/2 client ALPN fallback needs a handshake-complete signal that the TLS stage does not emit
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 35/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Área
- backend-api-design, networking
Línea de trabajo
Empieza por Http2AlpnSupport.scala:74 y Http2.scala:241,275; después sigue el recorrido por ProtocolSwitch.scala y Http2Blueprint.scala:146,327. Implementa la señal del engine por materialización y el switch de 4 puertos del lado del cliente descritos en el issue, incluido el almacenamiento en búfer de los elementos entrantes tempranos. Se considera terminado cuando se ofrecen los protocolos proporcionados y se selecciona el stack HTTP/1.1 o HTTP/2 negociado sin deadlock.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Split out from #483 (client-side HTTP/1.1 vs HTTP/2 protocol negotiation), which needs this solved first.
Code anchors below are against main @ 85d7243e7.
The blocker
The server already negotiates via ALPN and switches stacks: Http2Ext.httpsWithAlpn (Http2.scala:241) parks the chosen protocol in a mutable cell from setHandshakeApplicationProtocolSelector, and ProtocolSwitch (ProtocolSwitch.scala) installs either the HTTP/1.1 or HTTP/2 stack.
ProtocolSwitch makes that decision on the first inbound SessionBytes. That is sound server-side, because in HTTP the client always speaks first — there is always an inbound byte to trigger on.
Mirroring it on the client deadlocks. If negotiation lands on http/1.1, the server sends nothing until it receives a request, and the switch is sitting on that request waiting to learn the protocol. Neither side moves.
So the client needs a different trigger: a "handshake complete, ALPN result known" signal, delivered without depending on inbound application bytes.
Why the obvious signals don't work
- Pekko's
TLSstage emits no handshake-complete event.SslTlsInboundis only everSessionBytesorSessionTruncated, andSessionBytesonly arrives when there is application data. SSLSession(carried bySessionBytes) does not expose the negotiated ALPN protocol. OnlySSLEngine.getApplicationProtocoldoes.SSLEngine.setHandshakeApplicationProtocolSelectoris only meaningful for the peer that selects the protocol, i.e. the server.HandshakeCompletedListenerisSSLSocket-only;SSLEnginehas no equivalent.
Proposed fix
Wrap the engine returned by HttpsConnectionContext.engineCreator in a delegating SSLEngine that, on the first wrap/unwrap after which getApplicationProtocol goes non-null, completes a Promise[String]. The client-side switch stage installs the chosen layer from an AsyncCallback hung off that promise.
Notes on shape:
- Per-materialization state is required —
PersistentConnection.managedConnectionre-materializes the connection flow on every reconnect, so thehttpsWithAlpnapproach of a closed-overvarplus an "is not reusable" guard is not viable here. Building the stack insideFlow.fromMaterializergives a fresh promise and engine per materialization. - The switch stage must buffer inbound elements that arrive before the async callback is delivered (with h2, the server's SETTINGS frame can land first) and replay them on install.
- Types line up favourably:
Http.ClientLayer(Http.scala:794) isBidiFlow[HttpRequest, SslTlsOutbound, SslTlsInbound, HttpResponse, NotUsed], andHttp2Blueprint.clientStack(Http2Blueprint.scala:146).atop(unwrapTls)(:327) has that same shape. Both carryNotUsed, so the client switch needs none of theServerTerminatorplumbingProtocolSwitchcarries — but it is a 4-portBidiFlowstage rather than the server's 2-portFlow.
The delegation is ~30 mechanical methods, which is the main cost of this approach.
Alternative considered
A TimerGraphStageLogic polling engine.getApplicationProtocol is a few lines instead of a delegating engine, but puts a poll loop in the connection setup path. Recorded here as the fallback if the wrapper turns out to interact badly with the TLS stage.
Prerequisite bug
Http2JDKAlpnSupport.clientSetApplicationProtocols (Http2AlpnSupport.scala:74) ignores its protocols parameter and hardcodes Array("h2"):
def clientSetApplicationProtocols(engine: SSLEngine, protocols: Array[String]): Unit = {
val params = engine.getSSLParameters
params.setApplicationProtocols(Array("h2")) // should be `protocols`
engine.setSSLParameters(params)
}
Harmless today because the only caller (Http2.scala:275) passes Array("h2"), but this is exactly the seam negotiation needs — offering ["h2", "http/1.1"] is step one.
- Lenguaje dominante
- Scala
- Estrellas
- 196
- Forks
- 57
- Merge medio
- 1 d 20 h
- PR fusionados (30 d)
- 40
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de apache/pekko-http
-
dependencies
Dificultad 1/5 Menos de una hora Aptitud para principiantes 78/100
apache/pekko-http#1354 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 45/100
apache/pekko-http#1273 ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
apache/pekko-http#1248 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 42/100
apache/pekko-http#1180 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 30/100
apache/pekko-http#1112 · 1 comentario · 1 reacción ·
Los mantenedores suelen responder en 1 día
Todos los issues de apache/pekko-http
Issues similares
-
area:verification status:backlog
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
KD5UJC-XYZ/scarab#459 ·
Los mantenedores suelen responder en 1 día
-
A-api C-bug S-ready-for-human
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
ergoplatform/ergo#2838 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
Los mantenedores suelen responder en 1 día
-
llm4s (org.llm4s) is not indexedAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
scalacenter/scaladex#1834 ·
-
PlatformSpecific.hasGreenThreads incorrectly returns false for JDK updates and non-GA versionsPosiblemente ocupada @hearnadam la tomó hace 1 día. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
zio/zio#11303 · 1 reacción · 2 asignados ·
Los mantenedores suelen responder en 1 día