Hey everyone,
i'm new with Swift and specially with SwiftNIO. I'm trying to create a http server with Lifecycle stuff. Now my biggest problem is the next error.
NIOHTTP1/HTTPServerPipelineHandler.swift:104: Fatal error: Unexpectedly received a response in state idle
I think something happens and the readChannel function is executed when it should not.
The server creation code:
class http_server_test{
private let group: MultiThreadedEventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
private var server: ServerBootstrap
private let host = "127.0.0.1"
private let port = 8080
private var channel:Channel!
var lifecycle : ServiceLifecycle = ServiceLifecycle(configuration: ServiceLifecycle.Configuration(label: "http", installBacktrace: true))
init() {
server = ServerBootstrap(group: group)
.serverChannelOption(ChannelOptions.backlog, value: 256)
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
server
.childChannelInitializer { channel in
channel.pipeline.configureHTTPServerPipeline().flatMap {
channel.pipeline.addHandlers([Handler(&self.lifecycle)])
}
}
.childChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.childChannelOption(ChannelOptions.maxMessagesPerRead, value: 16)
}
public func start() {
print("Starting HTTP server...")
do {
channel = try server.bind(host: host, port: port).wait()
print("Server started and listening on \(channel.localAddress!)")
try channel.closeFuture.wait()
} catch {
print("ERROR")
}
}
public func stop() {
do {
try group.syncShutdownGracefully()
print("Server closed")
} catch {
print("ERROR")
}
}
}
My handler class code:
class Handler:ChannelInboundHandler {
typealias InboundIn = HTTPServerRequestPart
typealias OutboundOut = HTTPServerResponsePart
let logger = Logger(label: "SubSystemLifecycle")
let componentlifecycle: ComponentLifecycle = ComponentLifecycle(label: "SubSystem")
let router:Router = Router()
var isStarted = false
var pendingProcess = false
var context:ChannelHandlerContext? = nil
init(_ lifecycle: inout ServiceLifecycle) {
lifecycle.register(self.componentlifecycle)
componentlifecycle.start { error in
if let error = error {
print("Lifecycle failed starting ☠️: \(error)")
} else {
print("Lifecycle started successfully 🚀")
self.isStarted = true
if self.pendingProcess == true && self.context != nil {
self.move(context:self.context!)
}
}
}
}
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
print("I'am the channelRead")
router.setRequest(self.unwrapInboundIn(data))
self.context = context
if isStarted {
move(context: context)
}
else {
pendingProcess = true
}
}
// more methods...
}
The Router class method move only returns a simple html to show, there is nothing of NIO there.