Saturday, 6 February 2016

Create a Perfect Swift Server Project(from scratch) in Xcode

Perfect is a new framework for building server side applications in swift programming language. I recommend to pay a visit perfect.org and get the source code from github.

However, there is no tutorial for starting a new project yet. Given that, I will take my shot to explain at the best of my ability how to get a Perfect Server Up and Running in 8 Steps.

Step 1 : Clone the project from github

Perfect is not available in cocoapods yet. We are going to download the whole repository first but we are not going to use it directly as it is going to bloat our repository. Later when a pod is available we will disconnect it from our project and we will use the pod instead.

git clone https://github.com/PerfectlySoft/Perfect.git

Step 2 : Create a new workspace in xcode

The idea is to have the projects side by side, we are not going to touch Perfect it self, we just want to import the PerfectLib and PerfectServer frameworks
open Xcode and create a new Xcode workspace: 
  1. create a new directory and name for your project, let's name it MyPerfectWorkspace
  2. create a new xcode workspace File/New/Workspace...
  3. name our workspace by replacing "Untitled" with the name MyPerfectWorkspace
  4. navigate to the MyPerfectWorkspace directory and save your workspace

Step 3 : Create a new project in xcode

  1. File/New/Project...
  2. Select Cocoa Framework
  3. Add a Project Name for example MyPerfectProject
  4. Make sure Language option is set to Swift
  5. Make sure Include Unit Tests is checked
  6. click Next
  7. Navigate to the directory we created our workspace
  8. Make sure Create Git repository option is checked
  9. Set Add To option to the name of your workspace
  10. and finally click Create

Step 4 : Add the Dependencies to your Workspace

You will notice that we do not copy the dependencies in our project. That happens for a number of reasons :
  • We do not want to maintain 3rd party code, at least not in our project
  • Keeping the project in it's own directory/repository will allow us to update it easier with git
First we need to add the Library: 
  1. Ctrl+Click or Right Click to open the context menu in Project Navigator
  2. select Add files to "MyPerfectWorkspace"...
  3. navigate to the directory you cloned Perfect and select Perfect/PerfectLib/PerfectLib.xcodeproject
  4. have the options turned on and make sure that : 
    1. Copy items into destination... is unckecked. We do not want to copy the dependency
    2. Create folder references for any added folders is selected
  5. click Add

Then we need to import the PerfectServer project to use it as an abstraction of the launching process. We do the same thing as we did with PerfectLib.xcodeproject : 
  1. Ctrl+Click or Right Click to open the context menu in Project Navigator
  2. select Add files to "MyPerfectWorkspace"...
  3. navigate to the directory you cloned Perfect and select Perfect/PerfectServer/PerfectServer.xcodeproject
  4. have the options turned on and make sure that : 
    1. Copy items into destination... is unckecked. We do not want to copy the dependency in
    2. Create folder references for any added folders is selected
  5. click Add

Step 5: Setup your MyPerfectProject Scheme

  1. On the top of our Xcode IDE there is a breadcrumbs set active scheme input, click on the first element.
  2. select Edit scheme...
  3. to run through PerfectServer executable
    1. Select Run from the menu on the left
    2. Make sure you are on the Info tab
    3. Click Executable input to open it's options (it must be none at the moment) and select PerfectServer HTTP.app
    4. make sure we have shared option checked
We will notice that the icon of the scheme is changed from a framework suitcase to a swift app one.


Select MyPerfectProject and Run.  Now, we must be able to launch PerfectServer HTTP App when we run MyPerfectProject scheme.

We are not ready yet though. while we launch the HTTP Server we are not loading our framework as a module in, yet.

Step: 6: Link our project to the Library

Before we load our project as a module in "PerfectServerHTTP App" we need to make PerfectLib available for it.

To link PerfectLib to our project:
  1. Select MyPerfectProject" project in Project Navigator
  2. Select the target MyPerfectProject
  3. On the Linked Frameworks and Libraries section click +
  4. Under the Workspace section select PerfectLib.framework from 'PerfectLibOSX' target...
  5. Click Add


Step 7: Setup Project Build Settings

Then we need to set our Project Build Settings to build our project in directories that will allow "PerfectServerHTTP App" know about them and load our project(s) as a module.

Make sure you have your "MyPerfectProject" project selected in Project Navigator and the project.framework(The one with the suitcase icon) in the inspector>targets, then, select Build Settings Tab and set the following properties:
  • Deployment Location: Yes
  • Installation Build Products Location : $(CONFIGURATION_BUILD_DIR)
  • Installation Directory : /PerfectLibraries
  • Skip Install : NO
tip: use the search to filter the options

Step 8: Write Your "Hello World" Page

Now that we have all the plumping set we can start writing code. First we need to make our PerfectHandlers.swift file which will contain our init methods. Think about it as our main file.
  1. Ctrl+Click or Right Click to open the context menu in Project Navigator at the MyPerfectProject Group/Folder
  2. New File...
  3. select OS X>Swift File and click next 
  4. Name it PerfectHandlers.swift and click create
  5. copy/paste the following code in the new file
import PerfectLib
//public method that is being called by the server framework to initialise your module.
public func PerfectServerModuleInit() {

    // Install the built-in routing handler.
    // Using this system is optional and you could install your own system if desired.
    Routing.Handler.registerGlobally()

    // Create Routes
    Routing.Routes["GET", ["/", "index.html"] ] = { (_:WebResponse) in return IndexHandler() }

    // Check the console to see the logical structure of what was installed.
    print("\(Routing.Routes.description)")
}

//Create a handler for index Route
class IndexHandler: RequestHandler {

    func handleRequest(request: WebRequest, response: WebResponse) {
        response.appendBodyString("Hello World")
        response.requestCompletedCallback()
    }
}

Step 9: Run

Awesome! Now we have everything we need. To run the project make sure that you have set MyPerfectProject as active scheme and hit Cmd+R or the Play Button. 
When we run the application a few things happen:
  • The application launches a server "PerfectServerHttp" which renders a control window 
  • loads each module available in PerfectLibs
  • initialises the modules
  • broadcasts the server
Click at the black button to launch the index page and ta-daaaaah. We have a "Hello World" html page served from our new Perfect Server.

What's next

I would experiment a little with what Perfect framework provides, visit the Example and try a few of it's capabilities. On my next post I will try to explain what the public func PerfectServerModuleInit() does and I will explore the Routing and Handler Objects

Boilerplate - If you are lazy

You can clone my project and use it as a boilerplate if you feel lazy. find my source code in github. You still need to clone the Perfect source at the same directory.