Typed routes with Codables in Server Side Swift — Perfect

Fatih Nayebi
Server Side Swift
Published in
3 min readApr 8, 2018

Introduction of Codables in Swift 4 made our life way easier 😊, We no longer need to use parsing and mapping libraries or write a verbose code to extract / generate data structures such as JSONs.

Perfect framework adapted the Codables so we can create typed routes to easily decode and encode requests and responses in Server Side Swift. Let’s start with creating a function that returns main routes of our server. We will set our server’s routes by simply calling this function when we launch it.

As we may know and we can see from above, there are many ways to define routes, here I am going to explain four different ways:

  • Async routes (Not typed!)
  • Sync typed routes
  • Sync typed routes with custom HTTPResponse content
  • Async typed routes with custom HTTPResponse content and promises

There are more ways to define routes but examining these categories will give you a pretty good idea on how to mix and match different approaches.

options route is added to support SPA preflight calls

Asynchronous routes (Not typed!)

Although these types of routes are flexible and async, they are not type safe! 😬

Route for this handler is defined as:

routes.add(method: .get, uri: "/api/v1/user/logout", handler: logout)

Suppose we needed to extract the data out of the request, we need to extract the postBodyString first then decode it to our mode like the following:

Also, in this case we can return anything as JSON in the body of response and it’s not clear what this API will return as the handler function doesn’t return anything. Using Codables we could make it less verbose and type safe!

Synchronous typed route

These types of routes are useful when we do not need to call anything asynchronous (e.g. calling other APIs with PerfectCURL) but we are looking for type safety! 😊

Route for this handler is defined as:

routes.add(TRoute(method: .get, uri: "/healthcheck", handler: healthCheck))

Looking at method’s signature we can easily find out the return type that is already Codable and we do not need to generate a JSON out of it!

Synchronous typed routes with custom HTTPResponse Content

These types of routes are like previous category but they are more flexible in a sense that we can manipulate the response content (e.g. headers, http status,…)

Route for this handler is defined as:

routes.add(TRoute(method: .get, uri: "/api/v1/user/session", handler: session))

Asynchronous typed routes with custom HTTPResponse Content and Promises

Most of the time, APIs that we create are more complicated than just returning a JSON. For instance when we implement a login API we need to check user and password against database or we may call some other APIs asynchronously.

Meet asynchronous typed routes with HTTPResponse Content and Promises. 🎉These routes are the most flexible, type safe and performant routes 💪.

Route for this handler is defined as:

routes.add(TRoute<HTTPRequest>(method: .post, uri: "/api/v1/user/login", handler: login))

Extracting the model out of request is as simple as using the decode method on req (request). Also, it is async and returns a Promise that wraps our model so we do n’t need to generate a JSON manually! 😁

In this example, I created some helper methods to simplify the handlers:

  • json that actually sets the promise and returns the result to the client
  • error that returns the error to the client in cases of errors
  • incompleteRequest that will return 400 when we are not able to decode the request to our request object

IMHO, Async typed routes with HTTPResponse Contents and Promises are the best option as they are flexible, type safe and async so I encourage you to use them!

Finally, we can set our server’s routes like the following in the main.swift 😊

--

--

Fatih Nayebi
Server Side Swift

Data Scientist, Author of Swift Functional Programming Book, Lecturer at McGill University