Hummingbird Update

Almost 8 weeks back I published a post announcing the release of my Swift based http application framework hummingbird. This post is to update everyone on all the new stuff that has been added since that first post.

Web Application Layer (Hummingbird)

The web application layer has had a number of changes. Much of these have been API changes as I continue to refine the interfaces. I apologize to anymore who might have been using the framework and having to fix up their code on new releases. I promise the APIs will stabilise in the near future. Although async/await will probably cause some considerable changes.

The library has had a number of optimisations to improve performance. It is now according to The Benchmarker the fastest Swift server framework out there, if you want a 200 response with an empty body. I know these numbers don't necessarily mean much but its still nice to be in that position. TechEmpower report similar results from their Live results.

One minor addition, although I think it is worth noting, is a new protocol for defining a route. A route handler HBRouteHandler allows you to encapsulate all the components required for a route, and provide separation of the extraction of input parameters from the request and the processing of those parameters. For example

struct AddOrder: HBRouteHandler {
    struct Input: Decodable {
        let name: String
        let amount: Double
    struct Output: HBResponseEncodable {
        let id: String
    let input: Input
    let user: User

    init(from request: HBRequest) throws {
        self.input = try request.decode(as: Input.self)
        self.user = try request.auth.require(User.self)
    func handle(request: HBRequest) -> EventLoopFuture<Output> {
        let order = Order(user: self.user.id, details: self.input)
        return order.save(on: request.db)
            .map { .init(id: order.id) }
application.router.put("order", use: AddOrder.self)

HBRouteHandler doesn't provide a great deal of extra functionality, but it does provide a place to centralize all the components that make up a route.


Just after the initial release of Hummingbird I released a websocket library. The first release included a websocket server accessed via HBApplication.ws. Here is a basic example of a websocket server that returns everything that is sent to it

let app = HBApplication()
// add HTTP to WebSocket upgrade
// on websocket connect. 
app.ws.on("/ws") { req, ws in
    // send ping and wait for pong and repeat every 60 seconds
    ws.initiateAutoPing(interval: .seconds(60))
    // on read from client send the same data back
    ws.onRead { data, ws in

Given the code for a websocket client and server is almost identical setting up a client didn't take too much effort either and was included in a later release. I included a simple chat server example using websockets in the examples repository hummingbird-examples.

Mustache templating engine

Mustache is a "logicless" templating engine that can be used to create dynamic HTML. I have provided a Swift implementation of the engine HummingbirdMustache as a separate standalone project. It is a full implementatin of the mustache spec along with some additional bells and whistles. It supports all the standard tags along with transforms for transforming objects before being rendered, sequence context objects for rendered content based on position within a sequence, template inheritance for overriding sections of a partial and pragmas for setting implementation specific configuration parameters.


I guess the next big change is async/await. The initial release of swift including async/await will probably not have the support that Swift NIO needs to create an optimal HTTP server pipeline. So any initial release of Hummingbird with async/await will only include additive elements and will keep the Swift NIO EventLoopFuture interfaces. Async/await style routes and middleware will be available but I can't guarantee how performant they will be.