Kitura tutorial part 4: Configuration
Now that we have created a working endpoint in part 3, lets look at the configuration. At the moment, it’s all hard coded! We can do better than that.
If we’re ever going to run this application in the cloud, then it’s advantageous to use environment variables for configuration as per the 12 Factor App guidelines as these vary per deploy.
Environment variable configuration works especially well in containerised / VM applications, but can be a little more problematic when developing on your local computer as different apps may have the same envrionment variable names. To solve this,
.env files (pronounced “dotenv”) have become popular for storing configuration, especially in development and test environments.
We will use a
.env file locally, but not store it in version control.
# CouchDB configuration DB_HOSTNAME="localhost" DB_PORT=5984 DB_HTTPS=false DB_USERNAME=rob DB_PASSWORD=123456 DB_NAME=bookshelf_db # App configuration APP_PORT=8090
This file contains the 6 confiugration values we need for our CouchDB configuration along with the port we wish to run our API on as we may not always want to use port 8090.
.env files are only to be used in development, so we don’t need it in our git repository. Hence the first thing we do is add it to .gitignore:
.build/* Packages/* .env
To read our
.env file, we are going to use the SwiftDotEnv package. This library will read our
.env file and put the variables into the environment for us. It also provides some convenience methods for reading environment variables.
It is used like this:
import DotEnv let env = DotEnv() let someString = env.get("SOME_STRING") ?? "example" let someNumber = env.getInt("SOME_NUMBER") ?? 123 let someFlag = env.getBool("SOME_BOOLEAN") ?? true
As you can see,
DotEnv provides three get methods:
We then can use the nil coalescing operator (
??) to unwrap with a default if the environment variable doesn’t exist.
To install it, we add its GitHub URL to the
dependencies array in our
import PackageDescription let package = Package( name: "BookshelfAPI", dependencies: [ .Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 0, minor: 25), .Package(url: "https://github.com/IBM-Swift/HeliumLogger.git", majorVersion: 0, minor: 14), .Package(url: "https://github.com/IBM-Swift/Kitura-CouchDB.git", majorVersion: 0, minor: 25), .Package(url: "https://github.com/SwiftOnTheServer/SwiftDotEnv.git", majorVersion: 0), ] )
A quick run of
make will download the library into our
Packages directory and compile it.
We can now update
main.swift to take advantage of our new configuration system.
Firstly, we import the DotEnv module:
Now we can update our hardcoded configuration values:
let connectionProperties = ConnectionProperties( host: "localhost", port: 5984, secured: false, username: "rob", password: "123456" ) let databaseName = "bookshelf_db"
let env = DotEnv() let connectionProperties = ConnectionProperties( host: env.get("DB_HOST") ?? "localhost", port: Int16(env.getAsInt("DB_PORT") ?? 5984), secured: env.getAsBool("DB_HTTPS") ?? false, username: env.get("DB_USERNAME") ?? "rob", password: env.get("DB_PASSWORD") ?? "123456" ) let databaseName = env.get("DB_NAME") ?? "bookshelf_db"
We have now replaced all our hardcoded values with the value from the environment. If the environment variable doesn’t exist then we provide defaults so that the
?? operator can unwrap the Optional from the
We also need to update the port that Kitura will serve our API on:
Kitura.addHTTPServer(onPort: 8090, with: router)
let port = env.getAsInt("APP_PORT") ?? 8090 Kitura.addHTTPServer(onPort: port, with: router)
With those changes, you can now
make the app and run it. Nothing should change. However if you edit
.env and change, say
APP_PORT to 8091 then when you make and run you should see that it’s now listening on port 8091:
$ ./.build/debug/BookshelfAPI VERBOSE: init() Router.swift line 57 - Router initialized INFO: BookshelfAPI main.swift line 41 - Starting server VERBOSE: run() Kitura.swift line 44 - Staring Kitura framework... VERBOSE: run() Kitura.swift line 46 - Starting an HTTP Server on port 8091... INFO: listen(socket:port:) HTTPServer.swift line 132 - Listening on port 8091
Let’s now look at adding some more end points in part 5.
- Part 1: Getting Started with Kitura
- Part 2: CouchDB
- Part 3: List books
- Part 4: Configuration
- Part 5: Hypermedia
- Part 6: Adding a book
GitHub repository: kitura_bookshelfapi