Kitura Tutorial: Getting Started With Server-Side Swift
Do you wish your iOS skills worked on the backend? This Kitura tutorial will teach you to create RESTful APIs written entirely in Swift. By David Okun.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Kitura Tutorial: Getting Started With Server-Side Swift
30 mins
- Getting Started
- Installing CouchDB
- Kitura and RESTful API Routing
- Creating the Kitura Tutorial Project
- Troubleshooting Errors
- Using Kitura With Xcode
- Setting Up Your Kitura Server
- Creating Your Model
- Connecting to CouchDB
- Persisting Your Acronyms
- Creating Your Codable Routes
- Testing Your API
- Where to Go From Here?
Troubleshooting Errors
In case you get errors from swift build, enter the following in Terminal to verify your Swift version:
swift --version
If your version is lower than Swift 4.2.1, this is likely your problem. To fix this, make sure that you have the latest version of Xcode 10 installed, and then run the following command:
sudo xcode-select -s /Applications/Xcode.app
…where Xcode.app should be replaced the path to Xcode 10.
If you’re still having trouble, it’s possible that you’re using swiftenv
or another Swift version management tool, and you may need to manually set your Swift version to 4.2.1.
Here’s the command to do this if you’re using swiftenv
:
swiftenv global 4.2.1
Using Kitura With Xcode
Still in Terminal, at the root directory for your tutorial project, enter the following command:
swift package generate-xcodeproj
You should see this output:
generated: ./KituraTIL.xcodeproj
Enter this command to open your new Xcode project:
xed .
You’ll then be greeted with this view:
From here, you need to make sure that the selected target device is My Mac. After you select that, build and run (Command + R) your Xcode project, and you’ll see this printed to the console:
Hello, world!
Program ended with exit code: 0
Awesome! You’re now ready to get your back end app up and running!
Note: If you see the warning Conversion to Swift 4.2 is available, feel free to click it. There should be no changes needed. Just click Update again, to change their build settings.
Note: If you see the warning Conversion to Swift 4.2 is available, feel free to click it. There should be no changes needed. Just click Update again, to change their build settings.
Setting Up Your Kitura Server
You need only a few lines of code to set up your server with a router and a logger.
First, create a new Swift File named Application.swift in the Sources/KituraTIL group folder — the folder that contains main.swift. Make sure to add this file to the KituraTIL executable target:
Next, replace the contents of this file with the following:
import Kitura
import LoggerAPI
public class App {
// 1
let router = Router()
public func run() {
// 2
Kitura.addHTTPServer(onPort: 8080, with: router)
// 3
Kitura.run()
}
}
Here’s what this does:
- The Router will handle incoming requests by routing them to the appropriate endpoints.
- Here, you register
router
to run on port 8080. - Kitura will run infinitely on the main run loop after you call
run()
.
With your App
class created, open main.swift and replace its contents with the following:
import Kitura
import HeliumLogger
import LoggerAPI
HeliumLogger.use()
let app = App()
app.run()
The HeliumLogger.use()
command sets up HeliumLogger
as the default logger for Kitura. It’s good practice to
Then, you create an App
instance and run it.
Build and run, and you should see log messages from Kitura appear in the console.
Next, navigate to http://localhost:8080 in your browser, and you should see this page:
Congratulations, you’re now running a basic Swift-based HTTP Server on your local machine!
Creating Your Model
In this section, you’ll create a model type that represents an acronym.
Create a new Swift File named Acronym.swift, and remember to add it to the KituraTIL target.
Replace the contents of this file with the following:
// 1
import CouchDB
// 2
struct Acronym: Document {
// 3
let _id: String?
// 4
var _rev: String?
// 5
var short: String
var long: String
}
Here’s what you’ve done:
- You need to import this module so that you can make your
struct
conform to theDocument
protocol. - By making
Acronym
conform toDocument
, you’ll be able to leverage both Codable Routing and CouchDB’sDocument
protocol. You’ll learn more about Codable Routing shortly, butDocument
allows you to take advantage of the latest database driver for CouchDB. - As with most database drivers, you to have an
_id
property for your object — theDocument
protocol requires this. - CouchDB will also make you keep track of the latest revision of a document to confirm any update or delete actions you perform on an entry, so the
Document
protocol requires this_rev
property as well. - Lastly, the object itself requires you to store both a long form and short form acronym for the sake of this tutorial.
Build your project to make sure everything looks good. Remember, again, to double check that your new files are part of the KituraTIL target!
Notice that your object conforms to the Document
protocol. This is a mechanism that forces objects readable by the CouchDB database driver to also conform to Codable
, which is going to be extremely helpful during your journey with server-side Swift.
Codable
is simply a typealias
that combines the Encodable
and Decodable
protocols. This ensures conforming objects can be converted both to and from external representations. In particular, Kitura uses this to easily convert instances to and from JSON.
Before Kitura 2.0, you had to pass a request object into every endpoint closure, parse properties manually, cast appropriately, perform necessary transformations and finally create JSON to send as a response. It was a lot of work!
You can now leverage the power of Kitura’s Codable Routing to significantly reduce the boilerplate code in your routes. Win! You simply need to make your models conform to Codable
to take advantage of this, as you did above.
With this theory out of the way, it’s now time to connect your API to CouchDB.
Connecting to CouchDB
Open Application.swift, and replace its contents with the following:
// 1
import CouchDB
import Foundation
import Kitura
import LoggerAPI
public class App {
// 2
var client: CouchDBClient?
var database: Database?
let router = Router()
private func postInit() {
// 3
}
private func createNewDatabase() {
// 4
}
private func finalizeRoutes(with database: Database) {
// 5
}
public func run() {
// 6
postInit()
Kitura.addHTTPServer(onPort: 8080, with: router)
Kitura.run()
}
}
Going over these changes:
- You first import CouchDB in order to set up your persistence layer.
- You add the properties
client
for CouchDB anddatabase
to keep track of changes. - You’ll add code here after you’ve created your instance of
App
to connect to your database. - In case your
postInit()
method doesn’t find your database, it’ll create a new one for you. - Once you’ve set up your database, you’ll list all available routes for your API to match against here.
- You call
postInit()
from withinrun()
to make this part of your API setup.
Next, complete postInit()
by replacing // 3
with the following.:
// 1
let connectionProperties = ConnectionProperties(host: "localhost",
port: 5984,
secured: false)
client = CouchDBClient(connectionProperties: connectionProperties)
// 2
client!.retrieveDB("acronyms") { database, error in
guard let database = database else {
// 3
Log.info("Could not retrieve acronym database: "
+ "\(String(describing: error?.localizedDescription)) "
+ "- attempting to create new one.")
self.createNewDatabase()
return
}
// 4
Log.info("Acronyms database located - loading...")
self.finalizeRoutes(with: database)
}
Here’s what you just did:
- You create a
ConnectionProperties
object that you use to specify configuration values and a newCouchDBClient
. - You check to see if a matching database already exists, so you don’t overwrite existing data.
- If a database does not exist, you call
createNewDatabase()
to create a new database. - If a database does exist, you call
finalizeRoutes(with:)
to configure your routes.
Next, complete createNewDatabase()
by replacing // 4
with the following:
// 1
client?.createDB("acronyms") { database, error in
// 2
guard let database = database else {
Log.error("Could not create new database: "
+ "(\(String(describing: error?.localizedDescription))) "
+ "- acronym routes not created")
return
}
self.finalizeRoutes(with: database)
}
Here’s what this does, piece by piece:
- You create your database with a given name. You can choose anything, but it’s best to keep it simple.
- You ensure the database exists, or else, you abort and log an error.
- Just like before, you call
finalizeRoutes(with:)
to configure your routes.
You won’t be able to implement finalizeRoutes(with:)
just yet. You first need to complete your persistence layer. That’s what you’ll do in the next section.