9

Perfect is a new Swift Framework for creating a web/http server in swift. The documentation is not there yet and I find trouble with building a new project from scratch. I don't know which frameworks are necessary to import and which one is the entry point of the app. main.swift etc...

I'd like to make a new xcworkspace that will have my project, "a hello world server".

Problems I'm trying to tackle:

  • Which frameworks must be included?
  • How should I create a Perfect server, what's the entry point of the app?
  • How to create a "hello" root which responds with a "Hello World message"?
  • How should I make the target for the server and eventually run the server?

5 Answers5

5

I managed to write a "Hello World" guide about this. http://code-me-dirty.blogspot.co.uk/2016/02/creating-perfect-swift-server.html

In a nutshell you need to proceed like this:

  1. clone the original project

  2. Create a new Workspace

  3. Create a new Project

  4. Import PerfectLib.xcodeproject & Import PerfectServer.xcodeproject but do not copy

  5. Setup your project scheme to launch the PerfectServer HTTP App

  6. Link the PerfectLib onn the "Linked Frameworks and Libraries" section

  7. setup Build settings for your framework target*

  8. Create PerfectHandlers.swift and paste(better write to get the feeling) the following code

    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()
        }
    }
    

Then you are ready to run. On my blog I have a long, more detailed version of this and I will update here if necessary.

Build Settings

  • Deployment Location: Yes
  • Installation Build Products Location : $(CONFIGURATION_BUILD_DIR)
  • Installation Directory : /PerfectLibraries
  • Skip Install : NO
Community
  • 1
  • 1
4

I just wrote up a tutorial I want to share as another solution that outlines how to create a web service with Perfect and an app to interact with it.

http://chrismanahan.com/creating-a-web-service-swift-perfect

Summary

  1. You must have your project in a workspace. This workspace should also include the PerfectServer and PerfectLib projects.

workspace screenshot

  1. In your project, create a new OSX Framework target. This will be your server target

creating a new target

  1. Link PerfectLib with both your server target and your app's target (if you're building an app alongside the server)

  2. Edit your server's Run scheme to launch with PerfectServer HTTP App.

edit scheme scheme with executable

  1. In your Server target's Build Settings, set the following flags:

    • Skip Install = No
    • Deployment Location = Yes
    • Installation Directory = /PerfectLibraries
    • Installation Build Products Location = $(CONFIGURATION_BUILD_DIR)
  2. Create a new file in the server's folder. This file will handle requests that come in. Include [most of] the following:

    import PerfectLib
    
    // This function is required. The Perfect framework expects to find this function
    // to do initialization
    public func PerfectServerModuleInit() {
    
        // Install the built-in routing handler. 
        // This is required by Perfect to initialize everything
        Routing.Handler.registerGlobally()
    
        // These two routes are specific to the tutorial in the link above. 
        // This is where you would register your own endpoints. 
        // Take a look at the docs for the Routes API to better understand
        // everything you can do here
    
        // register a route for gettings posts
        Routing.Routes["GET", "/posts"] = { _ in
            return GetPostHandler()
        }
    
        // register a route for creating a new post
        Routing.Routes["POST", "/posts"] = { _ in
            return PostHandler()
        }
    }
    
    class GetPostHandler: RequestHandler {
        func handleRequest(request: WebRequest, response: WebResponse) {
            response.appendBodyString("get posts")
            response.requestCompletedCallback()
        }
    }
    
    class PostHandler: RequestHandler {
        func handleRequest(request: WebRequest, response: WebResponse) {
            response.appendBodyString("creating post")
            response.requestCompletedCallback()
        }
    }
    

As you're building out different aspects of your service, you can test it by using cURL in the command line, or other REST testing tools like Postman

If you wanna dive deeper and learn how to integrate with a SQLite database or create an app that talks with your new server, check out the tutorial at the top of this post.

Chris
  • 7,270
  • 19
  • 66
  • 110
  • Sure good job with your guide. You are taking the approach of just using PerfectLib which some would prefer. My approach is using the framework as much as possible. Including PerfectServer HTTP App. However, you do not answer the question directly in stackoverflow. Would you mind elaborating in stackoverflow please? Otherwise your answer might get flagged as non constructive as external links are supposed to be extras and not the main answer. Cheers – Alexandros Spyropoulos Feb 16 '16 at 09:45
  • 1
    Woops yeah you guys are right. I'll update my answer to include the appropriate steps – Chris Feb 16 '16 at 15:11
  • Both solutions work. This one is using directly the ParfectLib, so it could be considered skinnier. Mine is using the PerfectServer HTTP App so you get access to a flavours mechanism and a module loader. pick your poison. – Alexandros Spyropoulos Feb 23 '16 at 01:14
  • 2
    How do we host this on cloud? any tutorial on that – Anil Varghese Mar 05 '16 at 06:29
3

I would recommend staying away from the templates, as others suggested, and create a clean project yourself.

Create this folder structure:

MyAPI
├── Package.swift
└── Sources
    └── main.swift

Then, in the Package.swift file

import PackageDescription

let package = Package(
    name: "MyAPI",
    targets: [],
    dependencies: [
        .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2)
    ]
)

And the main.swift file:

import PerfectHTTP
import PerfectHTTPServer

do {

    let route = Route(method: .get, uri: "/hello", handler: { (request: HTTPRequest, response: HTTPResponse) in
        response.appendBody(string: "world!")
        response.completed()
    })

    try HTTPServer.launch(.server(name: "localhost", port: 8080, routes: [route]))

} catch {
    fatalError("\(error)")
}

Go to the command line and run:

swift package generate-xcodeproj

Open the generated project file:

MyAPI.xcodeproj

Change the active scheme, then build and run:

enter image description here

Open in safari:

http://localhost:8080/hello
nmdias
  • 3,888
  • 5
  • 36
  • 59
  • seems like it doesn't work for swift 4, I chenged Package.swift to .package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from:"2.0.0") and managed to successfully run 'swift package update' and 'swift package generate-xcodeproj' but I'm getting the error on import attempt: No such module 'PerfectLib' – BergP Oct 18 '17 at 08:57
0

I'm not sure if you have found a solution or not, but this is what I did:

The 'Tap Tracker' app is an app written the the Perfect libraries, so even if documentation isn't ready yet you can still dissect the app. I renamed the app, and the classes/methods. There's a single index.html, which I moved into a 'www' root, and then rerouted the view with TTHandler to try and make a standard layout. It doesn't work very well because the framework is so young, but it can be done. I would be much more specific but I went back to rails for the time being because I want to wait until it's a little more mature.

It's fun to mess around with, and I will probably write my own library on top of perfect onc feature innovation calms down and I can make something stable with it.

BleuGamer
  • 197
  • 2
  • 14
0

Just copy all files from one of the sample-projects to your git repository: https://github.com/PerfectExamples

Rename the example_project_name in all files (you've copied) to your project name.

In terminal run

swift package generate-xcodeproj

And you'll get a Perfect Project with the required name.

Naloiko Eugene
  • 2,453
  • 1
  • 28
  • 18