Skip to content

Commit aa3a7f1

Browse files
committed
Report connection errors on streams as HTTP/3 errors
Motivation: When the peer closes the connection, SwiftNetwork delivers the CONNECTION_CLOSE to every stream flow, so each stream's pipeline sees a 'QUICConnectionError' before the connection's pipeline does. The coordinator's own fan-out ('cancelStreamsDueToConnectionClose') can't reach those streams because they have already closed and deregistered by the time it runs. 'HTTP3StreamHandler' passed the error through untouched, so the owner of a request stream saw a QUIC error rather than an HTTP/3 one. It already translates the other two peer-close errors, RESET_STREAM and STOP_SENDING; CONNECTION_CLOSE was the missing third. Modifications: - Translate 'QUICConnectionError' into an 'HTTP3Error' with code 'remoteConnectionError' in 'HTTP3StreamHandler.errorCaught', keeping the peer's reason phrase and, for application errors, its error code. Result: Streams report HTTP/3 errors when the connection is closed by the peer
1 parent 393bc4f commit aa3a7f1

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

Sources/NIOHTTP3/HTTP3StreamHandler.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,20 @@ package final class HTTP3StreamHandler: ChannelDuplexHandler {
302302
case .none:
303303
break
304304
}
305+
case let error as QUICConnectionError:
306+
self.logger.trace("Caught CONNECTION_CLOSE")
307+
// RFC 9114 § 8: "Receipt of an unknown error code MUST be treated as equivalent to
308+
// H3_NO_ERROR."
309+
let h3Code = error.isApplication ? HTTP3ErrorCode(rawValue: error.code) ?? .H3_NO_ERROR : nil
310+
context.fireErrorCaught(
311+
HTTP3Error(
312+
code: .remoteConnectionError,
313+
message: error.reason,
314+
cause: error,
315+
errorCode: h3Code,
316+
location: .here()
317+
)
318+
)
305319
default:
306320
context.fireErrorCaught(error)
307321
}

0 commit comments

Comments
 (0)