no matter what i try, i cannot seem to send an HTTP/2 response using the new async API without corrupting the HTTP/2 stream.
extension NIOAsyncChannelOutboundWriter<HTTP2Frame.FramePayload>
{
func finish(
with message: ...) async throws
{
if let body:ByteBuffer = message.content
{
try await self.write(.headers(.init(headers: message.headers, endStream: false)))
try await self.write(.data(.init(data: .byteBuffer(body), endStream: true)))
}
else
{
try await self.write(.headers(.init(headers: message.headers, endStream: true)))
}
self.finish()
}
}
$ curl --http2 -v https://localhost
* Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN, offering h2
...
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x5607cf6a1e90)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/2
> Host: localhost
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8)
* stopped the pause stream!
* Connection #0 to host localhost left intact
curl: (92) HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8)
here’s the part that iterates the async sequence:
for try await stream:NIOAsyncChannel<
HTTP2Frame.FramePayload,
HTTP2Frame.FramePayload> in streams.inbound
{
let message:HTTP.ServerMessage<Authority, HPACKHeaders> = ...
try await stream.outbound.finish(with: message)
// pause for debugging
try await Task.sleep(for: .seconds(10))
try await connection.channel.close()
}
it worked fine with the old channel handler-based API! what on earth am i doing wrong?