Creating a console app. in Swift (on Linux)

The first thing we need to do is use the Swift CLI to generate the project etc. so run

swift package init --type executable

This will generate Sources folder, Tests, the Package.swift and even a README.md and .gitignore.

Now in the previous post we created a simple hello world Vapor REST server, so let’s write the code to call that from our console app.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

let session = URLSession.shared
let url = URL(string: "http://192.168.1.1:8080")

let semaphore = DispatchSemaphore(value: 0)

session.dataTask(with: url!) { (data, response, error) in
    let result = String.init(data: data!, encoding: .utf8)
    print(result!)
    semaphore.signal()
}.resume()

semaphore.wait()

Let’s break down this code…

The first bit of interest is the import. We need FoundationNetworking for the URLSession.shared within the Linux implementation (if I understand correctly) but not in the Mac OS version (I need to verify that). To allow us to only import FoundationNetworking if required, we use

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

As you’ve probably surmised URLSession is a shared resource, hence the shared singleton property.

Next we need the URL, which is pretty explanatory. Now the URLSession calls are asynchronous, hence if we just let this code run without the semaphore we’ll exit the application before the response from the web service returns.

The resume method is required to start the task (seems the wrong name to me, but there you go). See dataTask.

Finally we wait on the signal from the semaphore. Within the actual dataTask we’re just going to assume there’s data and no error (ofcourse in a real world application you’ll want to add a guard etc. to check for such things and also check the optionals actual have some value before unwrapping).

In this simple example we’ll simply assuming all worked, unwrap the data and print it to the console. Ofcourse the data will be encoded, so we’re need to create a string from the data and the required encoding as per the String.init.

Now just run the command

swift run

If all went well you’ll see the root level response from the web server code we wrote in the last post.