Home IOS Development Newbie’s information to server-side Swift utilizing the Hummingbird framework

Newbie’s information to server-side Swift utilizing the Hummingbird framework

0
Newbie’s information to server-side Swift utilizing the Hummingbird framework

[ad_1]

Swift on the Server in 2023

Three years in the past I began to concentrate on Vapor, the preferred web-framework written in Swift, which served me very nicely over time, however now it’s time to begin a brand new chapter in my life.

As I realized increasingly more about how servers work I noticed that Vapor has it is personal professionals and cons. The group modified lots in the course of the previous 3 years, some core members left and new individuals began to take care of the framework. I additionally had some struggles with the default template engine (Leaf) and just lately I began to show away from the summary database layer (Fluent) too. One other ache level for me is the rising variety of dependencies, I barely use websockets & multipart-kit, however Vapor has these dependencies by default and you may’t do away with them. 😢

Vapor has some very nice issues to supply, and for the general public it is nonetheless going to be an amazing selection for constructing backends for frontends (BFFs). For me, Vapor reached its limits and I needed to make use of one thing that feels a bit lighter. Somethings that’s modular, one thing that may be simply prolonged and matches my precise wants with out extra (unused) package deal dependencies.

This shiny new factor known as Hummingbird and it seems to be very promising. It was created by Adam Fowler who’s a member of the SSWG and in addition the primary writer of the Soto library (AWS Swift).

Hummingbird has a complete documentation accessible on-line and a pleasant instance repository containing numerous demo apps written utilizing the Hummingbird Swift server framework. I consider that the perfect a part of the the framework is modularity & extensibility. By the best way, Hummingbird works with out Basis, but it surely has extensions for Basis objects, it is a big plus for me, however perhaps that is simply my private desire these days. Hummingbird might be prolonged simply, you’ll find some very helpful extensions below the Hummingbird mission web page, lengthy story quick it really works with Fluent and it is comparatively straightforward to get together with it in case you have some Vapor information… 🤔

Getting began with Hummingbird

To start with, there isn’t any toolbox or command line utility to assist the kickoff course of, however you may all the time obtain the examples repository and use one of many tasks as a place to begin. Alternatively you may set all the things up by hand, that is what we’ll do now. 🔨

In an effort to construct a brand new utility utilizing the Hummingbird framework it’s best to create a brand new listing and initialize a brand new Swift package deal utilizing the next instructions:

mkdir server && cd $_
swift package deal init --type executable
open Bundle.swift

It will create a brand new Swift package deal and open the Bundle.swift file in Xcode. You should utilize your individual editor for those who don’t love Xcode, however both method you will have so as to add Hummingbird to your package deal manifest file as a dependency. We will setup an App goal for the applying itself, and a Server goal for the primary executable, which can use the applying and configure it as wanted.


import PackageDescription

let package deal = Bundle(
    title: "server",
    platforms: [
        .macOS(.v10_15),
    ],
    dependencies: [
        .package(
            url: "https://github.com/hummingbird-project/hummingbird",
            from: "1.0.0"
        ),
        .package(
            url: "https://github.com/apple/swift-argument-parser",
            from: "1.0.0"
        ),
    ],
    targets: [
        .executableTarget(
            name: "Server",
            dependencies: [
                .product(
                    name: "ArgumentParser",
                    package: "swift-argument-parser"
                ),
                .target(name: "App"),
            ]
        ),
        .goal(
            title: "App",
            dependencies: [
                .product(
                    name: "Hummingbird",
                    package: "hummingbird"
                ),
                .product(
                    name: "HummingbirdFoundation",
                    package: "hummingbird"
                ),
            ],
            swiftSettings: [
                .unsafeFlags(
                    ["-cross-module-optimization"],
                    .when(configuration: .launch)
                ),
            ]
        ),
        .testTarget(
            title: "AppTests",
            dependencies: [
                .product(
                    name: "HummingbirdXCT",
                    package: "hummingbird"
                ),
                .target(name: "App"),
            ]
        ),
    ]
)

Please create the required file and listing construction, as listed under, earlier than you proceed to the subsequent steps. It is vitally necessary to call issues as they seem, in any other case SPM will not work and the mission will not compile. Anyway, the mission construction is kind-of Vapor-like as you may see. 💧

.
├── Bundle.resolved
├── Bundle.swift
├── README.md
├── Sources
│ ├── App
│ │ └── HBApplication+Configure.swift
│ └── Server
│     └── major.swift
└── Checks
    └── AppTests
        └── AppTests.swift

The following step is to create the primary entry level for the applying. For this objective Hummingbird makes use of the Swift Argument Parser library. Place the next contents into the primary.swift file:

import ArgumentParser
import Hummingbird
import App

struct HummingbirdCommand: ParsableCommand {

    @Choice(title: .shortAndLong)
    var hostname: String = "127.0.0.1"

    @Choice(title: .shortAndLong)
    var port: Int = 8080

    func run() throws {
        let app = HBApplication(
            configuration: .init(
                deal with: .hostname(hostname, port: port),
                serverName: "Hummingbird"
            )
        )
        attempt app.configure()
        attempt app.begin()
        app.wait()
    }
}

HummingbirdCommand.major()

The HummingbirdCommand has two choices, you may setup a customized hostname and port by offering these values as command line choices (I am going to present it afterward), the applying itself will setup the deal with utilizing the enter after which it’s going to begin listening on the desired port.

The configure methodology comes from the App goal, that is the place you may customise your server occasion, register route handlers and stuff like that, identical to you’ll do that in Vapor. The primary distinction is that Hummingbird makes use of the HB namespace, which is fairly helpful, and the configure methodology is written as an extension. Let’s write it and register a fundamental route handler. 🧩

import Hummingbird
import HummingbirdFoundation

public extension HBApplication {

    func configure() throws {

        router.get("/") { _ in
            "Whats up, world!"
        }
    }
}

That is it. Now it’s best to be capable to run your server, you may press the Play button in Xcode that’ll begin your utility or enter one of many following instructions into the Terminal utility:

# simply run the server
swift run Server

# customized hostname and port
swift run Server --port 3000
swift run Server --hostname 0.0.0.0 --port 3000

# quick model
swift run Server -p 3000
swift run Server -h 0.0.0.0 -p 3000

# set the log degree (https://github.com/apple/swift-log#log-levels)
LOG_LEVEL=discover swift run Server -p 3000

# make launch construct
swift construct -c launch

# copy launch construct to the native folder
cp .construct/launch/Server ./Server

# run the executable
LOG_LEVEL=discover ./Server -p 3000

You may set these values in Xcode too, simply click on on the server scheme and choose the Edit Scheme… menu merchandise. Just remember to’re on the Run goal, displaying the Arguments tag. Merely provde the Arguments Handed On Launch choices to set a customized hostname or port and you may set the log degree by including a brand new merchandise into the Surroundings Variables part.

If you would like to unit check your utility, I’ve bought a excellent news for you. Hummingbird additionally comes with a pleasant utility instrument referred to as HummingbirdXCT, which you’ll be able to simply setup & use if you would like to run some assessments in opposition to your API. In our mission, merely alter the AppTests.swift file.

import Hummingbird
import HummingbirdXCT
import XCTest
@testable import App

ultimate class AppTests: XCTestCase {
    
    func testHelloWorld() throws {
        let app = HBApplication(testing: .reside)
        attempt app.configure()

        attempt app.XCTStart()
        defer { app.XCTStop() }

        attempt app.XCTExecute(uri: "/", methodology: .GET) { response in
            XCTAssertEqual(response.standing, .okay)

            let expectation = "Whats up, world!"
            let res = response.physique.map { String(buffer: $0) }
            XCTAssertEqual(res, expectation)
        }
    }
}

As an alternative of making the applying from the primary entry level, we will arrange a brand new HBApplication occasion, import the App framework and name the configure methodology on it. the XCT framework comes with a customized XCTStart and XCTStop methodology, and you may execute HTTP requests utilizing the XCTExecute operate. The response is offered in a completion block and it is attainable to look at the standing code and extract the physique utilizing a handy String initializer.

As you may see Hummingbird is sort of just like Vapor, but it surely’s light-weight and you may nonetheless add these further issues to your server when it’s wanted. Hummingbird seems like the subsequent iteration of Vapor. I actually do not know if Vapor 5, goes to repair the problems I am at present having with the framework or not, however I do not actually care, as a result of that launch will not occur anytime quickly.

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here