Skip to content

Commit

Permalink
Merge branch 'main' into ippmresponsiveness
Browse files Browse the repository at this point in the history
  • Loading branch information
glbrntt authored Jan 7, 2025
2 parents f4f37c7 + 066c8e4 commit b18f2a6
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
38 changes: 38 additions & 0 deletions Sources/NIOHTTPTypesHTTP2/HTTP2ToHTTPCodec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ public final class HTTP2FramePayloadToHTTPClientCodec: ChannelDuplexHandler, Rem
context.fireErrorCaught(error)
}
}

public func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {
if let ev = event as? NIOHTTP2FramePayloadToHTTPEvent, let code = ev.reset {
context.writeAndFlush(self.wrapOutboundOut(.rstStream(code)), promise: promise)
return
}
context.triggerUserOutboundEvent(event, promise: promise)
}
}

// MARK: - Server
Expand Down Expand Up @@ -262,4 +270,34 @@ public final class HTTP2FramePayloadToHTTPServerCodec: ChannelDuplexHandler, Rem
let transformedPayload = self.baseCodec.processOutboundData(responsePart, allocator: context.channel.allocator)
context.write(self.wrapOutboundOut(transformedPayload), promise: promise)
}

public func triggerUserOutboundEvent(context: ChannelHandlerContext, event: Any, promise: EventLoopPromise<Void>?) {
if let ev = event as? NIOHTTP2FramePayloadToHTTPEvent, let code = ev.reset {
context.writeAndFlush(self.wrapOutboundOut(.rstStream(code)), promise: promise)
return
}
context.triggerUserOutboundEvent(event, promise: promise)
}
}

/// Events that can be sent by the application to be handled by the `HTTP2StreamChannel`
public struct NIOHTTP2FramePayloadToHTTPEvent: Hashable, Sendable {
private enum Kind: Hashable, Sendable {
case reset(HTTP2ErrorCode)
}

private var kind: Kind

/// Send a `RST_STREAM` with the specified code
public static func reset(code: HTTP2ErrorCode) -> Self {
.init(kind: .reset(code))
}

/// Returns reset code if the event is a reset
public var reset: HTTP2ErrorCode? {
switch self.kind {
case .reset(let code):
return code
}
}
}
14 changes: 14 additions & 0 deletions Tests/NIOHTTPTypesHTTP2Tests/NIOHTTPTypesHTTP2Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,16 @@ final class NIOHTTPTypesHTTP2Tests: XCTestCase {

try self.channel.writeOutbound(HTTPRequestPart.head(Self.request))
try self.channel.writeOutbound(HTTPRequestPart.end(Self.trailers))
try self.channel.triggerUserOutboundEvent(NIOHTTP2FramePayloadToHTTPEvent.reset(code: .enhanceYourCalm)).wait()

XCTAssertEqual(try self.channel.readOutbound(as: HTTP2Frame.FramePayload.self)?.headers, Self.oldRequest)
XCTAssertEqual(try self.channel.readOutbound(as: HTTP2Frame.FramePayload.self)?.headers, Self.oldTrailers)
switch try self.channel.readOutbound(as: HTTP2Frame.FramePayload.self) {
case .rstStream(.enhanceYourCalm):
break
default:
XCTFail("expected reset")
}

try self.channel.writeInbound(HTTP2Frame.FramePayload(headers: Self.oldResponse))
try self.channel.writeInbound(HTTP2Frame.FramePayload(headers: Self.oldTrailers))
Expand All @@ -142,9 +149,16 @@ final class NIOHTTPTypesHTTP2Tests: XCTestCase {

try self.channel.writeOutbound(HTTPResponsePart.head(Self.response))
try self.channel.writeOutbound(HTTPResponsePart.end(Self.trailers))
try self.channel.triggerUserOutboundEvent(NIOHTTP2FramePayloadToHTTPEvent.reset(code: .enhanceYourCalm)).wait()

XCTAssertEqual(try self.channel.readOutbound(as: HTTP2Frame.FramePayload.self)?.headers, Self.oldResponse)
XCTAssertEqual(try self.channel.readOutbound(as: HTTP2Frame.FramePayload.self)?.headers, Self.oldTrailers)
switch try self.channel.readOutbound(as: HTTP2Frame.FramePayload.self) {
case .rstStream(.enhanceYourCalm):
break
default:
XCTFail("expected reset")
}

XCTAssertTrue(try self.channel.finish().isClean)
}
Expand Down

0 comments on commit b18f2a6

Please sign in to comment.