smoope / SwiftyTraverson

Other
7 stars 3 forks source link

SwiftyTraverson - Swift implementation of a Hypermedia API/HATEOAS client

Build Status

Introduction

This framework was inspired by Traverson javascript library.

Traverson allows you to follow the relation links within the HATEOAS-based API's response instead of hardcoding every single url. In addition, the built-in features allow you:

Installation

Traverson is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'SwiftyTraverson', '~> 1.0'

Usage

Initialization

let traverson = Traverson()

Configuration properties

Use Traverson.Builder in order to configure the Traverson:

let traverson = Traverson.Builder()
  .requestTimeout(2.0)
  .responseTimeout(5.0)
  .disableCache()
  .defaultHeader("Accept-Language", value: "de-CH")
.build()

List of available properties:

Property Description
requestTimeout Sets request timeout interval (in seconds) per each request. More details.
responseTimeout Sets response timeout interval (in seconds) per each request. More details.
disableCache Disables caching. More details.
defaultHeader Sets single default header which will be sent to the server per each request.
defaultHeaders Sets a collection of default headers which will be sent to the server per each request.
authenticator Authenticates every request accordingly to server's security policy. More details.
dispatchQueue Sets the queue in which the result handler get called

Making requests

Traverson supports the following HTTP method verbs to operate the data: GET, POST, PUT and DELETE. Below you'll find the examples of using each one of these verbs.

Retrieve data:

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .get { result, error in
    // Do something...
  }

Create data:

let objectToAdd: Dictionary<String, AnyObject> = ["name": "John Doe"]

traverson
  .from("http://www.some.com")
  .follow("users")
  .post(objectToAdd) { result, error in
    // Do something...
  }

Update data:

let objectToUpdate: Dictionary<String, AnyObject> = ["id": 1, "name": "John Doe"]

traverson
  .from("http://www.some.com")
  .follow("users", "first")
  .put(objectToUpdate) { result, error in
    // Do something...
  }

Delete data:

traverson
  .from("http://www.some.com")
  .follow("users")
  .delete { result, error in
    // Do something...
  }

As you might noticed, post and put methods expect an additional parameter represents the object should be created or updated, while get and delete has no such parameter.

Reading response

Each one of the described methods expects a callback function with the following parameters:

By default, SwiftyTraverson parses the response as SwiftyJSON's JSON object. If you like the native way, you can work with Dictionary:

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .get { result, _ in
    let json:JSON? = result.data
    let dictionary:[String: AnyObject]? = result.dictionary
    // Do something...
  }

Errors handling

Once something went wrong during the request, the callback's error variable will contain a description:

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .get { _, error in
    if let err = error {
      // Handle error...
    }
  }

Authenticating requests

In case of server requires an authentication, you can use built-in or custom implementation of TraversonAuthenticator protocol.

The example shows usage of HTTP basic authentication:

let traverson = Traverson.Builder()
  .authenticator(TraversonBasicAuthenticator(username: "username", password: "password"))
  .build()

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .get { result, error in
    // Do something...
  }

In some cases requests should be authenticated by default:

let traverson = Traverson.Builder()
  .authenticator(TraversonBasicAuthenticator(username: "username", password: "password"), preemptive: true)
  .build()

Sending additional information

It is possible to send an additional request-scoped information such as HTTP headers:

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .withHeader("Custom-Header", value: "Custom-Value")
  .get { result, error in
    // Do something...
  }

Since SwiftyTraverson supports URI templates (RFC 6570), passing a query parameters are possible as well:

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .withTemplateParameter("page", value: "1")
  .get { result, error in
    // Do something...
  }

or even an array:

traverson
  .from("http://www.some.com")
  .follow("users", "next")
  .withTemplateParameters(["user": "john", "page": "1", "sort": "color,desc"])
  .get { result, error in
    // Do something...
  }

Supposing we have the following URI template: http://www.some.com/{user}/{?page,sort}, it will be substituted to http://www.some.com/john/?page=1&sort=color,desc.

Reusing the same traverson instance

Once defined Traverson instance can be used multiple times by calling newRequest method:

traverson
  .from("http://www.some.com")
  .follow("users")
  .get { result, error in
    // Do something...
  }

...

traverson
  .newRequest()
  .follow("users")
  .post(objectToAdd) { result, error in
    // Do something...
  }

...

traverson
  .newRequest()
  .follow("users", "1")
  .delete{ result, error in
    // Do something...
  }

Supporting different media types

SwiftyTraverson expects that your server-side implementation follows HATEOAS principles, no matter which representation technology is used to render the response. Out-of-box it works with both JSON and JSON HAL standards.

In case of using simple JSON representation, you should specify it during the call:

traverson
  .from("http://www.some.com")
  .json()
  .follow("users", "next")
  .get { result, error in
    // Do something...
  }

Once your response fully follows the HAL standard you should do nothing, it's a default behavior. Alternatively, you can force use it:

traverson
  .from("http://www.some.com")
  .jsonHal()
  .follow("users", "next")
  .get { result, error in
    // Do something...
  }

Caching

By default, all the calls are cached by system framework. More details.

License

SwiftyTraverson is available under the Apache License, Version 2.0. See the LICENSE file for more info.