Sunday, January 22, 2017

Building Web Services with Swift and the Kitura framework

The Kitura framework, developed by IBM, is a light-weight, high-performance, web framework and server written in the Swift language.  This framework allows us to very quickly develop complex web services using the Swift language and Swift’s standard Foundation APIs.  This allows us to use our existing Swift knowledge to very easily create server-side services.  We can run our Kitura based services as stand-alone applications, deploy them to IBM’s Bluemix cloud or use IBM’s pre-build Docker image. 

If you are not familiar with what IBM is doing with Swift on the Server, you should check out their site:  https://developer.ibm.com/swift/. 

In the next few posts we will be looking at how we can use Kitura to develop web services with Swift.  For this first post, we will create some very basic web services to show how to setup a project that uses the Kitura framework and also how easy it is to use.  We will start off by creating the project using the Swift Package Manager. 

All the code for this post was written and tested on an Ubuntu 16.10 laptop.  The code should also work on macOS but you may need to install other dependencies. 

Let’s start off by creating a directory named hello and then initialize the project with the Swift package manager:

    mkdir hello
    cd hello
    swift package init

The first thing we need to do is add the Kitura framework as a dependency for our project.  We do this by adding the dependency to the Package.swift file.  The Package.swift file should have the following code in it:

  import PackageDescription

  let package = Package(
    name: "hello",
     dependencies: [
        .Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1, minor: 4)
     ]
  )

Now let’s create the main.swift file under the Sources directory and add the following code to it:

  import Kitura

  let router = Router()

  router.get("/hello") {
    request, response, next in
    response.send("Hello World!")
    next()
  }

  Kitura.addHTTPServer(onPort: 8090, with: router)

  Kitura.run()

The first line imports the Kitura framework so we can use it.  Next, we create an instance of the Router class.  The Router class provides an interface for routing the incoming requests.  This class lets us handle all the REST request types, Get, Post, Put and Delete. You can find the reference page for the Router class here:  http://ibm-swift.github.io/Kitura/Classes/Router.html#/s:FC6Kitura6Router3getFtGSqSS_7handlerGSaFzTCS_13RouterRequestCS_14RouterResponseFT_T__T___S0_

We use the get method to set up a router handler that will be invoked when an HTTP GET request comes in with a path pattern that matches the supplied path.  In this example, the path that we are matching against is “/hello”.   If a request does come in with the correct path, the code in the closure is called.  In our service, we send back a response that simply contains “Hello World!”.

We use the addHTTPServer(onPort:with:) to register the router.  The onPort parameter is the port number to bind the server too.  In this example, we will bind to port 8090.  This call only registers the server, it does not start listening until we call the run method in the last line.

Now let’s save the file and run Swift build from our project’s root directory.

If you receive an error that the compile could not find curl/curl.h, you will need to install the libcurl4-openssl-dev package (or any of the other three packages that provide the curl.h header file).  To do this run the following command:
sudo apt-get install libcurl4-openssl-dev

If everything compiles correct we can run the application with the following command from the project’s root directory:

  ./.build/debug/hello

We can verify that the application is running correctly but opening a web browser and putting 127.0.0.1:8090 in the address bar.  The screen that comes up should look something like this:


Now that we know Kitura is running, let’s test our service.  On Linux we have a command line tool called curl that can be used to make http requests.  To test our service run the following command:


If everything is running correctly we should receive the “Hello World!” message back from the server.  Getting back static messages isn’t that exciting but it does illustrate how to setup a project with Kitura and run it. 

Now let’s see how we could handle both path and request parameters with our GET requests.  A path parameter is a parameter that is part of the URL.  An example of a path parameter is:


where jon may be a parameter. 

An example of a request parameter is:


where we have a parameter named “name” with a value of “jon

Let’s look at how we would use path parameters first.  The only thing in our code that will change is the router’s get method and the closure.  The following code shows how we would handle path parameters:

  router.get("/hello/:name") {
    request, response, next in
    let name = request.parameters["name"] ?? ""
    response.send("Hello, \(name)")
    next()
  }

The path that we provide for the get method changed from “/hello” to “hello/:name”.  The “:name” part of the path defines the parameter.  We then use the coalescing operator to check the request to see if there is a parameter named “name”.  The line that does this is:

  let name = request.parameters["name"] ?? ""

Finally we send back a personalized response saying hello to the person whose name was provided in the path parameter.  We can build our project and test it with the following curl command:


Now let’s see how we can handle a request parameter.  The following code shows how we would handle request parameters:

  router.get("/hello") {
    request, response, next in
    let name = request.queryParameters["name"] ?? ""
 response.send("-Hello, \(name)")
    next()
  }

In this example the path that we provide for the get method is “/hello” which is the same as the path we provided in our original example.  We check the queryParameters property to see if we have a parameter named “name”.  The line that does this is:

  let name = request.queryParameters["name"] ?? ""

We can build our project and test it with the following curl command:

  curl http://127.0.0.1:8090/hello?name=jon


As we can see, from this brief introduction, Kitura is very easy to use.  IBM offers a number of frameworks that go along with Kitura, you can see the list here:  https://github.com/IBM-Swift/Kitura/wiki/Kitura-repositories.    In future posts, we will look at how we can use the projects to add logging to our Kitura services, use POST request, serialize and deserialize JSON and how to add a database for our services to use.

No comments:

Post a Comment