Server Side Programming in Swift
By: Pallav Trivedi
Tags: iOS App Development, Xcode, Backend, Swift Programming, Swift

We have always seen Swift as a language for building iOS/iPad apps (or maybe tvOS, watchOS, macOS). But, in one way or the other, we have always related it with Apple. The biggest fact that has been ignored is Swift can do a lot more than just building mobile apps.

I’ve seen mobile developers trying their hands on backend development and at the same time, struggling with new languages, frameworks like NodeJS/Go/Spring Boot etc. But, if Swift (a language that you are already comfortable with) is capable of building an entire backend, then why should we look for anything else.

Let’s start backend development using Swift at Server Side.

Use Case

In this article, we’ll try to mock the APIs for a flight booking app. To keep this post short, we’ll try two APIs (with dummy data) — one for getting the list of flights and one for getting the details of selected flights. This is how it looks like:

Detailed video tutorial can be found at this link.

Perfect

Instead of reinventing the wheel, we’ll use Perfect for doing the heavy lifting like creating HTTP Server, Routing etc.

What is Perfect?

Perfect is a web server and toolkit for developers using the Swift programming language to build applications and other REST services. It lets developers build using only Swift to program both the client-facing and server-side of their projects. It’s the ideal backbone for cloud and mobile technologies.

We can use Perfect for:

Creating HTTP Server

Routing

DB Connections (Mongo, MySQL, Maria, Postgres etc)

Web Sockets

File Handling

Server extensions for messaging queues (Kafka, Mosquitto, Zookeeper etc)

Deployment (directly on AWS EC2 instance)

… and a lot more

Let’s start with the creation of a Swift Package for the project. To do so, you must have Swift toolchain installed on your machine. If you have Xcode installed, then you are already using the Swift toolchain. But, if you’re not using Mac or Xcode, then you can follow these instructions for installation.

Go to the terminal and create a directory for the project (say ‘FlightBookingApp’) and navigate it.

mkdir FlightBookingApp

cd FlightBookingApp

2. Now create a Swift package using this command.

swift package init --type executable

3. Now that we have created the package, let’s create Xcode project from it (After all, Xcode is our favourite IDE 😛)

swift package generate-xcodeproj

4. Open the project in the Xcode and open the Package.swift.

5. To install Perfect as a dependency, add this line in the dependencies array.

.package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: “3.0.0")

6. Use ‘swift build’ from terminal to install the mentioned dependency (i.e. Perfect).

7. Once packages are downloaded from git, you’ll see a warning.Once packages are downloaded from git, you’ll see a warning -

Warning: dependency ‘perfect-httpserver’ is not used by any target

8. This is because we haven’t added Perfect to any target yet. To fix this, add this line in the dependencies array under targets array (Package.swift)

.product(name: "PerfectHTTPServer", package: "Perfect-HTTPServer")

9. Build the project (swift build) and generate the project again (swift package generate-xcodeproj)

10. Now in the main.swift, add the import statements for Perfect packages and create the server using this code.

10. Try running it using Cmd+R

If you get ‘Starting HTTP Server on 0.0.0:300’ in the console, that means the HTTP server is created and it’s listening on port 3000. You can change the port to 8080, 8181 or any other by changing the ‘serverPort’ variable.

server.serverPort = 3000

We have come a long way. Now it’s just about handling the routes. And before doing that, let’s create a proper directory structure.

Create three groups i.e. Data, Routes and Controllers. Data will have dummy data of flights. Routes will have a router for handling the requests. Controllers directory will have different controllers which will be called from the router.

5. Create a file FlightsData.swift in Data directory and dump some dummy data.

6. Dummy Data — https://gist.github.com/pallavtrivedi03/cf9b4f7a08d2d224934f912173c3db4a.js

7. In Controllers, create two files: FlightListController.swift and FlightsDetailController.swift.

8. In the Routes directory, create a file Router.swift.

9. In the FlightsListController, let’s write a function to return flight data. It will receive requests and responses of objects as arguments, and will return the JSON data for the flights.

10. Similarly, in the FlightsDetailController, let’s write a function for returning details of the requested flight.

11. To identify the details of which flight has been requested, we’ll take the id of the flight that is requested. For Example: http://127.0.0.1:3000/details/1001 , where 1001 is the id.

12. We’ll get ‘id’ from the ‘urlVariables’ property of the request object. If an id is missing, we would treat it as a bad request. Otherwise, we’ll fetch the data for the id and will return it as a response.

Ideally, you would be fetching these details from some database. But for this demo, we will be using the dummy data that we have dumped in FlightsData.swift.

Now that our controllers are set up, it’s just about connecting the routes.

1. Go to Router.swift and add a method setupRouter()

2. Create an object of Routes in this method and add two routes to it.

/flights

/details/{id}

3. {id} will be the id of the flight for which details are requested.

4. Call the controller’s methods from these routes and return the routes object.

Almost done.

The last piece of code that remains is to inform the servers about the routes.

Go to main.swift (where we created the server) and add this line

server.addRoutes(setupRouter())

Done.

2. Hit Command+R and give it a run.

3. If you get an error, port can be one of the reasons. The assigned port might already be in use by some other process. For making the port free, identification of the process is required to kill it.

lsof -n -i4TCP:3000 kill -9 <PID>

4. Now open the Postman/Insomnia or your favourite API client and try these routes.

http://localhost:3000/flights

http://127.0.0.1:3000/details/1001

6. Change the data, change the request type from get to post, add headers to the request and everything else that you want. Play around and explore Perfect.

7. For connecting to a database (Mongo, MySQL etc.) or for extending the server to messaging queues (Kafka, Zookeeper etc.) Perfect is just perfect for it.

Last but not the least, when you want to deploy the app, Perfect will help you with that too. Use Perfect Assistant and deploy seamlessly to the AWS EC2 instance.

Let’s break the stereotype and start using Swift for other stuff too.

Happy Coding :)