Clearing active handlers in response to external events?


I am using SwiftNIO ServerBootstrap as a HTTP/HTTPS proxy with connect handlers and I am wondering if there is any option to "clear" handlers for active connection based on some external event?

Because right now, once the handler is created and does initial connect, it may get reused for the same host multiple times. So for these cases I would want something like closeAllConnections method that would cause the handlers to be instantiated again for these connections.

Can I do this without tearing down the entire bootstrap with something like syncShutdownGracefully?

This is not frequent event.


You shouldn't need to tear down a bootstrap, only a Channel. Currently we don't have any way to remove all handlers from a Channel because it's a pretty unusual event. I'm a bit confused as to why you need to do this though: can you elaborate on the flow that would need this to happen?

Essentially there is some logic for the initial handler setup (when the connect happens) that changes based on time and other factors and I need to execute this bit of code again so the handler behaves bit differently for the same host if that makes sense.

Is there any reason not to trigger that based on a signal within the channel pipeline itself?

I am currently executing this logic at the start when handler gets the initial message partly because of performance, but mostly because I need to know the target URL for this code.

I think I could move it to channelRead possibly, but then the code would get executed way many times, right?

You can put it behind an if statement that knows the state though, can't you?

Well I don't know the state ahead of time in the handler, so I would need to use some kind of notifications or delegate to know how it should behave - hence why I want to recreate the handlers as easier solution.

I think without a more concrete example of what you're trying to do it's going to be hard to provide alternative patterns.

I have added simple pseudocode below to indicate where my custom logic happens. This is from the ConnectHandler.

And so the issue is that handleInitialMessage doesn't happen for existing connection.

Issue is that condition from my pseudocode is false and connect happens normally, but after short amount of time, the condition would evaluate to true.. And so if I were able to "clear" these handlers, handleInitialMessage would be called again for the same host and condition would work as expected.

private func handleInitialMessage(context: ChannelHandlerContext, data: InboundIn) {
        guard case .head(let head) = data else {
            self.logger.error("Invalid HTTP message type \(data)")
            self.httpErrorAndClose(context: context)
        }"\(head.method) \(head.uri) \(head.version)")

        guard head.method == .CONNECT else {
            self.logger.error("Invalid HTTP method: \(head.method)")
            self.httpErrorAndClose(context: context)

        let components = head.uri.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false)
        let host = components.first!  // There will always be a first.
        let port = components.last.flatMap { Int($0, radix: 10) } ?? 80  // Port 80 if not specified

        // Custom logic here
        if condition {
               self.httpErrorAndClose(context: context)

        self.upgradeState = .beganConnecting
        self.connectTo(host: String(host), port: port, context: context)

Hang on, are you saying that you're receiving a second CONNECT request on an existing connection?

Terms of Service

Privacy Policy

Cookie Policy