NIOAsyncChannelInboundStream + HTTP2: any point in checking endStream?

when iterating a NIOAsyncChannelInboundStream<HTTP2Frame.FramePayload>, is there any point in checking the FramePayloads for endStream?

No, NIOAsyncChannel is half-closure aware and should appropriately terminate the inbound stream after that message.

1 Like

this doesn’t seem to be the behavior i’m observing.

var body:[UInt8] = []
    body.reserveCapacity(length)

while let payload:HTTP2Frame.FramePayload = try await inbound.next()
{
    guard
    case .data(let payload) = payload,
    case .byteBuffer(let buffer) = payload.data
    else
    {
        continue
    }

    if  buffer.readableBytes <= length - body.count
    {
        buffer.withUnsafeReadableBytes { body += $0 }

        Log[.debug] = "received \(body.count) of \(length) bytes (end of stream: \(payload.endStream))"
    }
    else
    {
        return .badRequest("Payload too large")
    }
}

Log[.debug] = "stream finished"
debug: bound to :::8443
debug: received 21 of 21 bytes (end of stream: true)

one client timeout duration later…

debug: stream finished

should i file a bug?

Oh good catch, I went back and double-checked.

This is probably not a bug: you can still receive frames on a stream that has had END_STREAM set on it. In particular, WINDOW_UPDATE frames can still be received, and potentially other extension control frames.

For this reason, swift-nio-http2 doesn't send half-closure on END_STREAM, which means NIOAsyncChannel doesn't help you here.

Sorry to mislead you: in this case, END_STREAM is important and you should observe it.

Note, however, that if you also send END_STREAM then everything should tear itself down appropriately.

2 Likes