HTTP/2 client ALPN fallback needs a handshake-complete signal that the TLS stage does not emit
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Lĩnh vực
- backend-api-design, networking
Hướng nghiên cứu
Bắt đầu với Http2AlpnSupport.scala:74 và Http2.scala:241,275, sau đó lần theo ProtocolSwitch.scala và Http2Blueprint.scala:146,327. Triển khai tín hiệu engine cho mỗi materialization và switch 4 cổng phía client được mô tả trong issue, bao gồm việc buffering các phần tử inbound đến sớm. Hoàn tất có nghĩa là cung cấp các protocol được chỉ định và chọn stack HTTP/1.1 hoặc HTTP/2 đã đàm phán mà không xảy ra deadlock.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- Scala
- Star
- 196
- Fork
- 56
- Merge trung bình
- 1 ngày 18 giờ
- Pull request đã merge (30 ngày)
- 43
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của apache/pekko-http
-
dependencies
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
apache/pekko-http#1354 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 45/100
apache/pekko-http#1273 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
apache/pekko-http#1248 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
apache/pekko-http#1180 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
apache/pekko-http#1112 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của apache/pekko-http
Issue tương tự
-
agent-ready area/dev-tooling kind/docs-only layer/docs size/XS
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
marola-dev/marola#855 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
llm4s-ollama: bind a base-URL variable for chat sections, and align the documented variable nameĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
scylladb/scylla-migrator#413 ·
-
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 70/100
-
[Bug] HiveDialect shares its colspecs dict with SQLAlchemy's DefaultDialect (python/pyhive)Có thể đã có người làm @rusackas đã nhận 1 ngày trước. Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 80/100
apache/kyuubi#7786 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày