Pragmatism in the real world

Getting started with Zewo

Zewo is a set of Swift packages that enable writing HTTP services. Most of the packages are focussed around this goal, but it also includes adapters for MySQL and PostgreSQL which is useful.

The HTTP server is called Epoch and you can combine it with Router and Middleware to make a working API.

To get going I wrote a simple /ping end point to see how it fits together.

Epoch is built on libvenice (a fork of libmill), http_parser and uri_parser which are all C libraries that we need to install.

As we’re on Ubuntu (because that’s the only officially supported Linux distribution for Swift at the moment), we can use the pre-packaged libraries provided by Zewo:

$ echo "deb [trusted=yes] ./" | sudo tee --append /etc/apt/sources.list
$ sudo apt-get-update
$ sudo apt-get install uri-parser http-parser libvenice

Once this is done, we create a normal SPM application by creating a new directory and creating Package.swift and main.swift within it.

$ mkdir api1
$ cd api1
$ touch Package.swift
$ touch main.swift

Package.swift is used to define our dependencies. In this case we just need Epoch:

import PackageDescription

let package = Package(
    name: "api1",
    dependencies: [
        .Package(url:"", versions: Version(0,0,1)..<Version(1,0,0)),
        .Package(url:"", versions: Version(0,0,1)..<Version(1,0,0))

main.swift is our application:

import Glibc
import HTTP
import Router
import Epoch

let router = Router { routerBuilder in

    routerBuilder.get("/ping") { request in

        let now = time(nil)

        return Response(
            status: .OK, 
            json: [
                "time" : .NumberValue(Double(now))

Server(port: 8889, responder:router).start()

This is a very simple API. It simply responds to /ping with the current timestamp.

Firstly we import the relevant modules. We need Glibc for time(), HTTP for Response, Router and Epoch.

We then instantiate a Router by passing a closure to the constructor. We are given a RouterBuilder object into our closure which we can use to define routes using get(), post(), etc.

In our case, we define a get route of "/ping" which again takes a closure which gives us a Request and we must return a Response. This is very similar to what we do in Slim and every other framework of a similar ilk, such as Express.

Our action simply gets the time using the standard C library function and returns a Response with a status of OK and a JSON encoded object containing our timestamp.

Finally we instantiate a Server, telling it the port number and router to use as a responder and start() it.

We build and run our app using:

$ swift build
$ .build/debug/api1

This will start an HTTP server on port 8889 which responds to /ping:

Swift ping

And we’re done.

2 thoughts on “Getting started with Zewo

Comments are closed.