NIO HTTP1 or HTTP2 Async Server

Does anyone know of example code for a SwiftNIO HTTP1 or HTTP2 server that uses the async/await paradigm. I want to convert my SwiftNIO server (that was at one point derived from the sample code that is already a part of the SwiftNIO project) to use async/await instead.

Do you mean rewrite the whole thing using async/await or just providing async/await APIs?

Both Vapor and Hummingbird have added swift concurrency APIs but the internals are still NIO.

NIO has some helpers to move between EventLoops and Swift Concurrency. If you want to move from NIO to Swift Concurrency EventLoopFuture.get() is an async function that returns the result of a fulfilled EventLoopFuture. If you want to move from Swift Concurrency to NIO EventLoopPromise.completeWithTask() will complete a promise with the results of an async function.

1 Like

You may also want to check out this guide about swift concurrency adoption in the server landscape: guides/concurrency-adoption-guidelines.md at main ยท swift-server/guides ยท GitHub

I am only using SwiftNIO. I just want to see a basic example of a SwiftNIO HTTP1 or 2 server using async/await. Preferably the old example upgraded. I need to study it before I make any changes. I know that I need to go async/await asap, but I have a lot more studying to do.

I'm not sure you need to go async/await asap, but yes it is worth looking into now, to be prepared.

SwiftNIO is still running on EventLoops, it has had virtually no changes related to async/await added so far, outside of helpers that allow you to move between EventLoops and Swift Concurrency.

I don't know of any simple examples, but the links I posted above were to demonstrate what other server frameworks had done to provide async/await support. Without knowing exactly what you are trying to do, below is an example of how you might convert a function responding to a request read in by a server with a response.

Originally you might have had a function like below. This returns an EventLoopFuture that will be fulfilled with the response to the request

func respond(to: Request, on eventLoop: EventLoop) -> EventLoopFuture<Response> {
    ...
}

To move into a swift concurrency world you want to convert to this

func asyncRespond(to: Request) async throws -> Response

You need a new version of the original function that translates between EventLoops and Swift Concurrency

func respond(to: Request, on eventLoop: EventLoop) -> EventLoopFuture<Response> {
    let promise = eventLoop.makePromise(of: Response.self)
    promise.completeWithTask {
        // call async version of function
        try await asyncRespond(to: request)
    }
    return promise.futureResult
}

This is a very simple example, read the guide @ktoso posted. It is full of loads of useful info. There is an example NIO http client here

2 Likes