Repository: apple/swift-nio
File: Sources/NIOHTTP1/NIOTypedHTTPServerUpgradeHandler.swift (Swift)

Code before:
            break
        }
    }

    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
        switch self.stateMachine.channelReadData(data) {
        case .unwrapData:
            let requestPart = Self.unwrapInboundIn(data)
            self.channelRead(context: context, requestPart: requestPart)

        case .fireChannelRead:
            context.fireChannelRead(data)

        case .none:
            break
        }
    }

    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {
        switch event {
        case let evt as ChannelEvent where evt == ChannelEvent.inputClosed:
            // The remote peer half-closed the channel during the upgrade. Should we close the other side
            switch self.stateMachine.inputClosed() {
            case .close:
                self.upgradeResultPromise.fail(ChannelError.inputClosed)
                context.close(promise: nil)
            case .continue:
                break
            case .fireInputClosedEvent:
                context.fireUserInboundEventTriggered(event)
            }

        default:
            context.fireUserInboundEventTriggered(event)
        }
    }

    private func channelRead(context: ChannelHandlerContext, requestPart: HTTPServerRequestPart) {
        switch self.stateMachine.channelReadRequestPart(requestPart) {
        case .failUpgradePromise(let error):
            self.upgradeResultPromise.fail(error)

        case .runNotUpgradingInitializer:
            self.notUpgradingCompletionHandler(context.channel)
                .hop(to: context.eventLoop)
                .whenComplete { result in
                    self.upgradingHandlerCompleted(context: context, result, requestHeadAndProtocol: nil)
                }

        case .findUpgrader(let head, let requestedProtocols, let allHeaderNames, let connectionHeader):
            let protocolIterator = requestedProtocols.makeIterator()

Review comment (bug):
Can we switch these two lines around so we first call close and then fulfil the promise. This should avoid potential bugs where the promise callbacks interact with the channel.

Code after:
            break
        }
    }

    public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
        switch self.stateMachine.channelReadData(data) {
        case .unwrapData:
            let requestPart = Self.unwrapInboundIn(data)
            self.channelRead(context: context, requestPart: requestPart)

        case .fireChannelRead:
            context.fireChannelRead(data)

        case .none:
            break
        }
    }

    public func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {
        switch event {
        case let evt as ChannelEvent where evt == ChannelEvent.inputClosed:
            // The remote peer half-closed the channel during the upgrade. Should we close the other side
            switch self.stateMachine.inputClosed() {
            case .close:
                context.close(promise: nil)
                self.upgradeResultPromise.fail(ChannelError.inputClosed)
            case .continue:
                break
            case .fireInputClosedEvent:
                context.fireUserInboundEventTriggered(event)
            }

        default:
            context.fireUserInboundEventTriggered(event)
        }
    }

    private func channelRead(context: ChannelHandlerContext, requestPart: HTTPServerRequestPart) {
        switch self.stateMachine.channelReadRequestPart(requestPart) {
        case .failUpgradePromise(let error):
            self.upgradeResultPromise.fail(error)

        case .runNotUpgradingInitializer:
            self.notUpgradingCompletionHandler(context.channel)
                .hop(to: context.eventLoop)
                .whenComplete { result in
                    self.upgradingHandlerCompleted(context: context, result, requestHeadAndProtocol: nil)
                }

        case .findUpgrader(let head, let requestedProtocols, let allHeaderNames, let connectionHeader):
            let protocolIterator = requestedProtocols.makeIterator()