/ Swift 3

Server-side Swift

I used to be a backend developer for a very long time. I always loved it. First it started with PHP, and now Node.js is the preferred language for my backend systems. The main question is this: are we going to use Swift in the near future as a full stack language?

Current state of server-side Swift

Libraries

My personal favorite / winner: Noze.io

Right now we have many popular backend frameworks written in Swift. Some of them are sponsored by a big company, but there are some hidden gems. Let me show you the most popular frameworks first:

Perfect

Is it?

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer

// Create HTTP server.
let server = HTTPServer()

// Register your own routes and handlers
var routes = Routes()
routes.add(method: .get, uri: "/", handler: {
        request, response in
        response.setHeader(.contentType, value: "text/html")
        response.appendBody(string: "<html><title>Hello, world!</title><body>Hello, world!</body></html>")
        response.completed()
    }
)

// Add the routes to the server.
server.addRoutes(routes)

// Set a listen port of 8181
server.serverPort = 8181

do {
    // Launch the HTTP server.
    try server.start()
} catch PerfectError.networkError(let err, let msg) {
    print("Network error thrown: \(err) \(msg)")
}
Vapor

It's raining.

import Vapor

let drop = Droplet()

drop.get("/hello") { _ in
  return "Hello Vapor"
}

drop.run()
Kitura

Like a boss.

import Kitura

// Create a new router
let router = Router()

// Handle HTTP GET requests to /
router.get("/") {
    request, response, next in
    response.send("Hello, World!")
    next()
}

// Add an HTTP server and connect it to the router
Kitura.addHTTPServer(onPort: 8090, with: router)

// Start the Kitura runloop (this call never returns)
Kitura.run()
Zewo

Not bad.

import HTTPServer

let log = LogMiddleware()

let router = BasicRouter { route in
    route.get("/hello") { request in
        return Response(body: "Hello, world!")
    }
}

let server = try Server(port: 8080, middleware: [log], responder: router)
try server.start()

As you can see most of the libraries implemented the same middleware pattern - which is great. Perfect is the oldest - if I remember correctly - and most mature one, it supports many database connectors, and it has a nice API. Vapor is really simple, Kitura is supported by IBM, and Zewo was my latest discovery.

Benchmarks

There is a really nice benchmark article here, I'd like to link the results:
UPDATE: this one is more fresh and accurate (thanks @Dan_Appel).

Perfect wins in almost every category. Kitura scored well, but if I want to be honest, I really don't like Kitura. When I tried it, it was a pain in the ass to get it up and running, and that setup process marked the product for me. Anyway, Vapor is not as good as it seems, and I don't like it's API at all. Zewo has a good memory management model, but it's slow.

==That's it? ==

Nope, but before we dive in, there is a second benchmark which compares Vapor to some other not-swift web frameworks. You can see that native Go and Node.js rocks, but they are not as fast as Swift can be...

The others

Swift Express

The expressjs copycat.

import Express

let app = express()

app.get("/hello") { request in
    return Action.ok("Hello world!")
}
app.listen(9999).onSuccess { server in
    print("Express was successfully launched on port", server.port)
}

app.run()
Swifter

Naming your project sucks.

let server = HttpServer()
server["/hello"] = { .ok(.html("You asked for \($0)"))  }
server.start()
Taylor

The deprecated girl.

import Taylor

let server = Taylor.Server()

server.get("/") { req, res in
    res.bodyString = "Hello, world!"
    return .Send
}

let port = 3002
do {
   print("Starting server on port: \(port)")
   try server.serveHTTP(port: port, forever: true)
} catch {
   print("Server start failed \(error)")
}
Embassy / Ambassador

Like politics.

import Embassy
import EnvoyAmbassador

let loop = try! SelectorEventLoop(selector: try! KqueueSelector())
let router = Router()
let server = HTTPServer(eventLoop: loop, app: router.app, port: 8080)

router["/api/v2/users"] = DelayResponse(JSONResponse(handler: { _ -> AnyObject in
    return [
        ["id": "01", "name": "john"],
        ["id": "02", "name": "tom"]
    ]
}))

// Start HTTP server to listen on the port
try! server.start()

// Run event loop
loop.runForever()
Criollo

Penguins are not welcomed.

let server = CRHTTPServer()
server.get("/") { (request, response, completionHandler) in
    response.send("Hello world!")
}
server.startListening()

Noze.io

Node.js without javascript.

import http

http.createServer { req, res in 
  res.writeHead(200, [ "Content-Type": "text/html" ])
  res.end("<h1>Hello World</h1>")
}
.listen(1337)

Stop here for a moment.

WHY THE FUCK HAS THIS LIBRARY ONLY 130 STARS ON GITHUB?

Guys, if you want to see an amazing library, you should check this. I was impressed by the quality of the code, and the amount of work that the authors have put into this little project. It's unbelievably sad - for me - that they don't get bigger attention, because they deserve it.

I love Node.js, I really do. I always said that Objective-C is like javascript, but with a different syntax. Think about this:

Swift = Javascript + speed + type safety

Node.js is getting fucked with the io.js fiasco, ES7 and babel and the npmjs "ecosystem" which is getting horrible nowadays, this is why Swift has the perfect opportunity to steal some market share from Node.js. Noze.io is the perfect entry point for those who programmed in node. Same libraries, same syntax - more ore less - and a new beginning to have a clean start.

The only problem is Swift itself - at least for one more year.

The future

I would really love to use Noze.io in production, but Swift has so many bugs that this is impossible. A few days ago Apple announced that they're going to clean up the mess and they're going to make an integrated low level server side API.

Look at the names. Members from the "big four" (Perfect, Vapor, Kitura, Zewo) are already involved. I really believe that these libraries are going to disappear and we'll have a native server side solution in pure Swift.

After Swift 4 is going to be released things are going to change a lot. We'll have a stable ABI, the language will be mature enough so this will lead us to the point where we can use Swift as a real productional full-stack language.

Finally let me answer the original question:

are we going to use Swift in the near future as a full stack language?

YES, definitely.

PS.: If you are crazy enough to make your own server, this tutorial can help you too.