Swift Backend Web Services Using Swift Express

Since Apple released swift as an open source language, there’s been various discussions going on making use of its openness, especially In the field backend services.

Why backend web services? As a iOS Developer, we would be pretty comfortable using the same language and logic that can be used for apps as well as backend.

When we came to know, swift language has been announced as Open source. The first thing which came to our team mind was, Is It possible to create web applications and backend web services using swift language. From there we started exploring various Apple community and forum sites.

The “Swift Express” Is the one framework, which we thought very easy to use, due to its perfect documentation and we thought of giving a try on this new framework. The swift-express webserver project developed and run by CrossLabs. Swift-Express frameworks inherited the features of Play Framework and Express.js.


    1. Play framework: High-productivity Java and Scala web application framework that integrates the components and APIs needed for web application development.

 

  1. Express.js :Express is a minimal and flexible Node.js a web application framework that provides a robust set of features for web and mobile applications.

Let's dive In and take a look at Swift Express

You need to have Xcode 7.2 or newer version.

Installation

  • First you need to Install HomeBrew In your machine.
  • Next, Open your terminal and type the following commands.
$ brew tap crossroadlabs/tap
$ brew install swift-express

Let's create a small project to create an API service for user registration

In your terminal, type the following command to create a project In any our destination path and once project Is created go to the folder.

$ swift-express init HelloExpress
$ cd HelloExpress

Next type "swift-express bootstrap". This command will download or update all the dependencies files Into the project.

$ swift-express bootstrap

Once the build succeeds, Open the project.

$ open HelloExpress.xcodeproj 

As soon as Xcode opens your project, go to main.swift and notice we already have all the necessary code we need in there in order to start the server.

import Express

let app = express()

app.views.register(StencilViewEngine())

app.get("/assets/:file+", action: StaticAction(path: "public", param:"file"))

app.get("/") { (request:Request)->Action in
return Action.render("index", context: ["hello": "Hello,", "swift": "Swift", "express": "Express!"])
}

app.listen(8080).onSuccess { server in
print("Express was successfully launched on port", server.port)
}

app.run()

Our project will be running In the localhost port number: 8080.

Let's run our project and see what output we will get. To run the project, type following commands In terminal and Open your browser and type http://localhost:8080/

$ swift-express build
$ swift-express run

If everything went well, you should see following response on your browser.

Now, let's create a sample API.which responds back to us, whenever we pass any params along with URL. Go to main.swift file and Type following code

app.get("/hello") { request in
return Action.ok(request.query["message"]?.first) // app.get() -> Specifies its a "GET" method
}

Now,test it in the browser at localhost:8080/hello?message=Hello.You should see a white screen with Hello written on it, or whatever string you choose to put after the = character in the URL.

Now our local server setup is complete. Lets a write a simple SignUp API for user registration using Swift-Express.

User Registration - POST Method

app.post("/api/user") { request in
//check if JSON has arrived
guard let json = request.body?.asJSON() else {
return Action.ok("Invalid request")
}

if let firstName = json["first_name"].string
{
if firstName.characters.count < 1 || firstName.stringByReplacingOccurrencesOfString(" ", withString:"") == ""
{
let firstResponse =
["status": "false",
"description": "first Name name must contain one character"]
return Action.render(JsonView.name,context:firstResponse)
}
}

if let lastName = json["last_name"].string
{
if lastName.characters.count < 1 || lastName.stringByReplacingOccurrencesOfString(" ", withString:"") == ""
{
let lastResponse =
["status": "false",
"description": "last Name name must contain one character"]
return Action.render(JsonView.name,context:lastResponse)
}
}

if let email = json["email"].string
{
if !HelperClass.sharedHelper.isValidEmail(email)
{
let emailResponse =
["status": "false",
"description": "Invalid Email"]
return Action.render(JsonView.name,context:emailResponse)
}
}

if let password = json["password"].string
{
if !HelperClass.sharedHelper.isPasswordValid(password)
{
let passwordResponse =
["status": "false",
"description": "password should contain one uppercase,one lower case and one special character"]
return Action.render(JsonView.name,context:passwordResponse)
}
}

//compose the response as a simple dictionary
let response =
["status": "true",
"description": "User created succesfully"]

//render dictionary as json (remember the one we've registered above?)
return Action.render(JsonView.name, context: response)
}

You can download the singleton Helper class here HelperClass

As we finished our signUp API.Lets test this API, by creating simple signup page app.

Create a new project of Single view. Add four textfields and a button .Its should look somewhat below screenshot and make a necessary IBOulet and IBAction connection.

Lets create "Network connection class" to make connect with our localhost and call this class has "GWebengine.swift",its a subclass of NSObject.

Please find the following link to download "GWebengine.swift" class. GWebEngine

In ViewController, make a API call on the SignUp Button action. and add the necessary call back delegate methods In default ViewController class.

ViewController.Swift
class ViewController: UIViewController,WebEngineDelegate
On SignUp Button Action
  @IBAction func signUpBtnPressed(sender: AnyObject)
{
let signUpDict = NSMutableDictionary()
signUpDict.setObject(firstNameTextField.text!.uppercaseString, forKey:"first_name")
signUpDict.setObject(lastNameTextField.text!, forKey:"last_name")
signUpDict.setObject(emailTextField.text!, forKey:"email")
signUpDict.setObject(passwordTextField.text!, forKey:"password")
GWebengine.sharedInstance.delegate = self
GWebengine.sharedInstance.sendRegisterRequest(signUpDict)
}
GWebEngine Delegate Methods
    func connectionManagerDidRecieveResponse(pResultDict: NSDictionary)
{
let desp:String?
let title:String?
let success = pResultDict.objectForKey("status") as! String
if success == "true"
{
desp = pResultDict.objectForKey("description") as? String
title = "Success"
}
else
{
desp = pResultDict.objectForKey("description") as? String
title = "Oops!"
}
commonErrorAlert(title!, alertMessage:desp!)

}

func connectionManagerDidFailWithError(error: NSError)
{
commonErrorAlert("Oops!", alertMessage:error.localizedDescription)
}

//Common alertview for displaying localized error
func commonErrorAlert(titleMessage:String,alertMessage:String)
{
let alert = UIAlertController(title:titleMessage, message:alertMessage, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alert, animated: true, completion: nil)
}

You can download complete project here Swiftbackend & HelloExpress API

Swift Express:Simple, yet unopinionated web application server written in Swift

Topics: Webservices, Backend, Mobility