HTTP/2 stream stays half-closed after an early response with status >= 300
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 55/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- swift
- Lĩnh vực
- backend, networking
Hướng nghiên cứu
Start with HTTP2ClientRequestHandler.runSuccessfulFinalAction and the state machine path described in the issue; compare how .close is handled for an early response while the request body is incomplete. Run swift test --filter 'HTTP2ClientRequestHandlerTests/testStreamIs' using the added tests in Tests/AsyncHTTPClientTests/HTTP2ClientRequestHandlerTests.swift. Done means the client sends RST_STREAM(CANCEL), the stream is released, and shutdown() completes.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
AsyncHTTPClient commit hash: 017115279d09dbfd262a6c678e96d31c90b3b2aa (main).
Context
After an early complete response with status >= 300 (RFC 9113, section 8.1), the client sends neither END_STREAM nor RST_STREAM. The stream stays half-closed (remote), and the connection counts it as open. HTTPClient.shutdown() does not complete until the connection closes. Status < 300 is a different case: #922.
Example: apple/containerization sends each blob PUT without credentials first, and the registry answers 401 during the upload.
Cause:
- The request body is not complete.
HTTPRequestStateMachinereturns.forwardResponseEnd(.close, ...). - Since #657,
HTTP2ClientRequestHandler.runSuccessfulFinalActionignores.close, because "an h2 stream is closed after every request anyway". This is not true here. The request body stream is paused, and the.finishedstate machine rejects more body parts and the request end. HTTP2IdleHandlergets noStreamClosedEventfor this stream.- At
shutdown(), the stream getsHTTPConnectionEvent.shutdownRequested. The request is finished, sorequestCancelled()returns.wait.
Steps to reproduce
The repro sends one 64 MiB PUT without credentials to registry-1.docker.io over HTTP/2. The registry answers 401 during the upload.
git clone https://github.com/beshkenadze/async-http-client-early-response-leak
cd async-http-client-early-response-leak
AHC_REVISION=0171152 ./run.sh # AHC main
The README has the commands for 1.36.2, a lazy body and --wait 660, the output fields and the requirements.
The tests use only in-memory channels. git and SwiftPM need network access. The commands add only the fix branch's new tests to main:
git clone https://github.com/swift-server/async-http-client.git
cd async-http-client
git checkout 017115279d09dbfd262a6c678e96d31c90b3b2aa
git fetch https://github.com/beshkenadze/async-http-client.git fix/h2-reset-stream-after-early-response
git checkout FETCH_HEAD -- Tests/AsyncHTTPClientTests/HTTP2ClientRequestHandlerTests.swift
swift test --filter 'HTTP2ClientRequestHandlerTests/testStreamIs'
Expected result
The client sends RST_STREAM(CANCEL). The connection releases the stream, and shutdown() completes.
Actual result
| Run | openH2Streams |
shutdown() |
|---|---|---|
main and 1.36.2, eager and lazy body, 2 runs each |
1, in 8 of 8 runs | Does not complete in 10 s, in 8 of 8 runs. |
1.36.2, eager body, --wait 660, 1 run |
The stream and the connection closed together 61 s after the start of the run. | Completed at once after the 660 s wait. |
The fix for #939 does not change these results in 4 runs. The raw data names that build local@afcf468. Its Sources/ tree (6b69592) is the same as in beshkenadze:fix/early-response-request-body-stream.
| Test | Result |
|---|---|
testStreamIsClosedIfErrorResponseEndsBeforeRequestBodyIsSent |
Fails. After an early 401, the stream channel is still active (XCTAssertFalse failed). |
testStreamIsResetIfErrorResponseEndsBeforeRequestBodyIsSent |
Fails. The client sends no RST_STREAM: XCTAssertEqual failed: ("[]") is not equal to ("[HTTP2ErrorCode<0x8 Cancel>]") |
| The other 2 of the 4 tests | Pass. |
Raw data:
Environment
swift-nio-http2 1.46.0, macOS 27.0.1 (26A434).
$ swift --version
swift-driver version: 1.168.6 Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)
Target: arm64-apple-macosx27.0.0
$ uname -srvm
Darwin 27.0.0 Darwin Kernel Version 27.0.0: Tue Aug 11 21:22:49 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T6000 arm64
- Ngôn ngữ chính
- Swift
- Star
- 1.1k
- Fork
- 159
- Merge trung bình
- 1 giờ 22 phút
- Pull request đã merge (30 ngày)
- 3
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 swift-server/async-http-client
-
RFC: pluggable authenticator APIĐang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
swift-server/async-http-client#946 · 2 bình luận ·
-
RequestBag keeps the request body after an early response with status >= 300Có thể đã có người làm @beshkenadze đã nhận 14 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
-
Transaction keeps the request body after an early response with status >= 300Có thể đã có người làm @beshkenadze đã nhận 14 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 22/100
-
Invalid state: idleĐang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
swift-server/async-http-client#927 · 2 bình luận ·
Tất cả issue của swift-server/async-http-client
Issue tương tự
-
feat: 앱 정보에 개인정보처리방침과 고객지원 연결Có thể đã có người làm @xrpjwk8 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
DeveloperAcademy-POSTECH/2026-C6-A13-Hear-I-am#120 ·
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 76/100
swiftlang/swift-java#955 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Add a Light view to SurfUIĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
michaelnisi/hanstholm#246 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[投稿] SSE 接收的三层检查:字节、事件与响应终态Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
jaywcjlove/quick-rss#448 ·
-
Edit Space… → Save overwrites an imported space's SF Symbol icon with 🌱 and stacks both glyphsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
VictorKildahl/cra#205 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày