Welkin's Secret Garden

First Glimpse of Swift Server

Following the footstep of open source Swift and the announcement of supporting linux, developers in open source communities spare no efforts to make Swift a better language, thus Swift heat rise and meanwhile, frameworks of Swift Server were born.

Searching on Github with key word Swift Server,I list top three frameworks with most stars.

  1. Perfect
  2. vapor
  3. Kitura

Among them, Kitura is released by IBM , however I choose Perfect , the framework with the most stars, to begin my trip at last.

The First Sight of Perfect

On the home page of Perfect, it leaves me an impression that it is well documented. So, let’s go.

Environment Configuration

Perfect is based on Swift 3.0. But as an iOS developers, having installed the latest version of Xcode means everything is okay.

Template

There is a basic template on the site, so you just clone it.

1
git clone https://github.com/PerfectlySoft/PerfectTemplate.git

And build.

1
2
cd PerfectTemplate
swift build

Then it begins to download its dependent packages.

Run it.

1
.build/debug/PerfectTemplate

It’s more convenient to run on Xcode, right?

1
swift package generate-xcodeproj

Well, xcodeproj appears.

The Code

Turning to the project folder, we find it consists of several parts:

  • .build : compiler made
  • Package : dependence
  • Sources : source code, is equivalent to src
  • webroot : for static files, is equivalent to webapps

Luckily, I have some Java EE experience, so this is easy to understand.

main

Select the main file, then you can find the config of the project.

1
2
3
4
5
6
7
8
9
10
let server = HTTPServer()
server.addRoutes(routes)
server.serverPort = 8181
server.documentRoot = "./webroot"
configureServer(server)
do {
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: \(err) \(msg)")
}

Actually, it creates a HTTPServer , and then set the route, port and root path , and starts at last. That’s all.

Routes

Routes, it is equivalent to the Controller in Spring MVC . It defines the URL and the handling method of revceiving a request. As for adding a new request handler:

1
2
3
4
5
6
routes.add(method: .get, uri: "/hello", handler: {
request, response in
response.setHeader(.contentType, value: "text/html")
response.appendBody(string: "HI")
response.completed()
})

Just like this.

WebSocket

If you need WebSocket to keep alive, the only thing is to add a dependence in Package.swift.

1
.Package(url:"https://github.com/PerfectlySoft/Perfect-WebSockets.git", majorVersion: 2, minor: 0)

And swift build in console.

Then create a class, implementing WebSocketSessionHandler .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class EchoHandler: WebSocketSessionHandler {	
func handleSession(request: HTTPRequest, socket: WebSocket) {
socket.readStringMessage {
string, op, fin in
guard let string = string else {
// This block will be executed if, for example, the browser window is closed.
print("no string")
socket.close()
return
}

print("Read msg: \(string) op: \(op) fin: \(fin)")

socket.sendStringMessage(string: "Hello", final: true) {
print("sent")
self.handleSession(request: request, socket: socket)
}
}
}
}

This makes Server return a “Hello” when it receives message from Client.

Then add a route to receive the request.

1
2
3
4
5
6
7
routes.add(method: .get, uri: "/echo", handler: {
request, response in
WebSocketHandler(handlerProducer: {
(request: HTTPRequest, protocols: [String]) -> WebSocketSessionHandler? in
return EchoHandler()
}).handleRequest(request: request, response: response)
})

That’s it for today. As for database and deployment, I think there will not be any problem with its detailed documents. Maybe I will mark down something about that when I try accessing them.

@end