Swift, Perfect, mustache and PostgreSQL on Heroku

As every iOS developer, sometimes I feel that for a new app I’d better have a back-end: some simple server that will store data and pass it to client on iOS in some specific shape. The only problem— I’m too lazy to study new languages and frameworks like Ruby on Rails, got no time for diving into web. But since Swift became open source and many (maybe even too many) web frameworks were created, laziness no longer has excuse.

So, by the end of this series of tutorials we’ll:

  1. create server with Perfect web framework on mac
  2. use Mustache templates for responses
  3. connect PostgreSQL database to store some data
  4. and deploy whole thing to Heroku

Don’t ask why I’ve picked these tools. There are many other swift web frameworks today (Kitura, Curassow, Vapor), Perfect has SQLite out of the box (there is good tutorial by Chris Manahan). It can be easily deployed to Amazon AWS or Docker, also.

Part 1. Make it work on Mac

First of all, we need to clone Perfect toolkit from github (by the moment when this tutorial was published, latest release was 1.0). This can be done in Terminal with git utility, but I got used to SourceTree application and will not cover git commands here.

Folders we are interested in:

  1. PerfectLib — library itself
  2. PerfectServer — backend server supporting FastCGI or stand-alone HTTP. On mac we’ll run our project via server OS X app from it.
  3. Connectors/PostgreSQL — lib for communication with PostgreSQL database

Step 1.1 Set up project

So, lets create new Xcode project with OS X — CocoaFramework template, check Swift to be chosen as a language:

Than we have to link PerfectLib, PerfectServer and PostgreSQL to our project. Click on the + in Linked Frameworks and Libraries section, than Add Other and choose next files one by one:

  1. where_your_clone_of_perfect_lives/PerfectLib/PerfectLib.xcodeproj
  2. where_your_clone_of_perfect_lives/PerfectServer/PerfectServer.xcodeproj
  3. where_your_clone_of_perfect_lives/Connectors/PostgreSQL/PostgreSQL.xcodeproj

These projects are seen in the Project Navigator on the left. Also, now when you’ll click on + you should see something like that:

We’ll need to choose PerfectLib.framework from ‘PerfectLibOSX’ target and PostgreSQL.framework and add them.

Now go to Build Settings and change following lines:

  • Skip Install = No
  • Deployment Location = Yes
  • Installation Directory = /PerfectLibraries
  • Installation Build Products Location = $(CONFIGURATION_BUILD_DIR)

And the last thing to set up is Scheme — cuz our CatFoodServer should be run inside Perfect HTTP server app. Choose CatFoodServer — Edit Scheme and choose PerfectServerHTTP.app as an executable:

Now, when you’ll hit Run button, Xcode will build the project, attach your server app to PerfectServerHTTP.app and run it:

Step 1.2 Build Simple Service

Roughly, our service workcycle looks like:

  1. http server is waiting for requests from client (browser, app, curl in Terminal, Postman plugin from Chrome, whatever)
  2. client is sending Get request to url of one of mustache templates
  3. a) server looks at %handler pragma in mustache template 
    b) finds if any PageHandlers are registered for this pragma
    c) runs its valuesForResponse(context: MustacheEvaluationContext, collector: MustacheEvaluationOutputCollector) throws -> MustacheEvaluationContext.MapType method which should return dictionary with mustache pragmas as keys and values that should be filled on their places in template
    d) fills mustache pragmas with values according to their keys
  4. if everything ok, server responds with code 200 and filled mustache
  5. if handler was not set properly or some kind of error happened, server will respond with code 500 and error description

Don't worry if point 3 does not make sense to you, we’ll dive into it right now.

Step 1.2.1 Mustache template

Ordinary Mustache template looks like this:

Hello {{name}}
Your beard trimmer will arrive on {{format(date)}}.
{{#late}}
Well, on {{format(realDate)}} because of a Martian attack.
{{/late}}

and if we’ll pass PerfectLib’s built-in parser dictionary like

let data = [
"name": "Arthur",
"date": NSDate(),
"realDate": NSDate().dateByAddingTimeInterval(60*60*24*3),
"late": true
]

the {{…}} marks will be filled with these values according to keys.

Lets start with something simple. Create Mustache folder (we will store all our templates there, just for our comfort in future) and file CatName.mustache inside:

Our template will have only two pragmas :

  • handler — identifier to wire template to correct PageHandler. Identifier is not necessary to be same as file’s name; in request user will write filename, identifier is used inside the app only.
  • name which will be replaced by String while server will compose response

Write to CatName.mustache:

{{% handler:CatName}}My cats name is {{name}}

Really simple, yeah? Last thing to check is that this file will be copied to root of our web service so PerfectServerHTTP knew where to find it.

Go to Build Phases, add Copy Files Phase, check Destination — Products Directory, subpath webroot (yes, it’s the same webroot which you’ve seen in app’s window when pushed Run button) and add our template:

Step 1.2.2 Finally some Swift!

This part will be really short — thanks to Perfect. Add PerfectHandlers.swift file with contents:

Global public function PerfectServerModuleInit() is required by Perfect to perform initializations. Inside we are defining which class is in charge of processing witch request — or via registering PageHandlers like we do here, or via setting routing like in tutorial by Chris Manahan.

Now add CatNameHandler.swift file and implement CatNameHandler class inside:

CatNameHandler conforms to PageHandler protocol, and implements method valuesForResponse(_: _:), described in Perfect’s documentation in such a way:

This function is called by the system in order for the handler to generate the values which will be used to complete the mustache template. Returns the dictionary of values which will be used when populating the mustache template.

So inside we are simply creating dictionary with only key from our template — “name”, and name of my cat — “Sasha”.

That’s it! Build and Run.

Step 1.2.3 Check that all works

You can install Postman in Chrome, use curl utility in Terminal or simply put localhost:8181/catname or 0.0.0.0:8181/catname in your browser. Yes, since we did not specify weather server should reply with our template to GET or POST requests, both will work same way — as I’ve described in 5-points-list above.

Cool!

Project in this state in branch step_1.2_build_simple_service on github.


In next steps we will create PostgreSQL database on mac, access it from our server app and populate more complicated mustache template.


These tutorials are participating in Perfect’s contest. If you’ve liked — please, be kind to thumb up here, Sasha wants moar food!