A JBoss Project
Red Hat

Aerogear Guides Tutorials to help get you off and running.

AeroGear Http

Introduction

AeroGear Http library is designed to be a convenient wrapper against the facilities provided by the underlying foundation networking, based on NSURLSession. In particular, it provides the following features:

  • Convenient expose of HTTP verbs

  • Pluggable Request and Response serializers with built-in support for URL Enconding and JSON

  • Upload (plus MultiPart support) and Download

  • HTTP Basic/Digest authentication support

HTTP verbs

The library exposes common HTTP verbs as methods, taking care of encoding the parameters passed in. Here is an example usage:

var http = Http(baseURL: "http://server.com")

http.GET("/endpoint",  parameters: ["param": "value"], completionHandler: {(response, error) in
    // handle response
})

http.POST("/endpoint",  parameters: ["param": "value"], completionHandler: {(response, error) in
    // handle response
})
..
// ...similarly, PUT, DELETE and HEAD can be called
The request is always executed asynchronously in a background thread whereas the completion callbacks are conveniently called in the main thread to give you the chance to update the UI.
In the example above, we used the optional 'baseURL' parameter of the remote application in order to avoid specifying it on each request. The constructor accepts further parameters that can customize it’s behavior e.g setting a custom NSURLSessionConfiguration. Head over to the API documentation for more information.

By default, the Http object will conveniently use the built-in JSON request and response serializers. See the next section on how you can customize it and create your own.

Pluggable Request and Response serializers

The constructor of the Http object accepts serializers for both the request and response. For the former, objects must conform to the RequestSerializer protocol, whereas for the latter it accepts objects conforming to the ResponseSerializer protocol.

RequestSerializer

When constructing the task to execute, the library will call RequestSerializer::request method to construct the appropriate NSURLRequest to use, passing along any parameters passed by the user:

func request(url: NSURL, method: HttpMethod, parameters: [String : AnyObject]?, headers: [String : String]?) -> NSURLRequest

The library already comes with built-in implementations of the form HttpRequestSerializer and JsonRequestSerializer. The former is a generic http serializer which encodes user’s parameters to either on URL, or on the body of the request, depending on the http method utilized, whereas the latter encodes the parameters in JSON. Use them as a starting point for your own serializers.

ResponseSerializer

Once the request has been made and a response is received, the library will call ResponseSerializer::validateResponse and if valid will then call ResponseSerializer::response method to process the data received. Here are the signatures of those methods:

func validateResponse(response: NSURLResponse!, data: NSData, error: NSErrorPointer) -> Bool

func response(data: NSData) -> (AnyObject?)

The library already comes with built-in implementation of the form JsonResponseSerializer and StringResponseSerializer. The former serializes the response to JSON whereas the latter returns the data as a simple String object. Use them as a starting point for your own serializers.

Upload and Download

The library offers convenient access to upload and download mechanism offered by the perform plus the ability to perform a multipart upload.

Upload

Here is an example usage on how to perform upload of a file:

var http = Http(baseURL: "http://server.com")

let fileURL = NSBundle.mainBundle().URLForResource("file", withExtension: "txt")

http.upload("/upload",  file:fileURL,
    progress: { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)  in
        println("bytesWritten: \(bytesWritten), totalBytesWritten: \(totalBytesWritten), totalBytesExpectedToWrite: \(totalBytesExpectedToWrite)")
    }, completionHandler: { (response, error) in
        // handle response
})
Internally and if not specified, the method will use 'POST' when performing upload, but you can choose to override it by passing an appropriate HttpMethod in the 'method' parameter.

Apart from NSURL objects pointing to local files you can also use an NSData or an NSStream convenient methods.

Multipart Upload

Here is an example on how you can perform a multipart upload:

var http = Http(baseURL: "http://httpbin.org")

let file = MultiPartData(data: data, name: "lorem", filename: "lorem.txt", mimeType: "plain/text")

http.POST("/upload",  parameters: ["key": "value", "file": file], completionHandler: {(response, error) in
    // handle response
})

The difference with the post request shown earlier, is that on the request parameters list we add a MultiPartData object which has it’s data initialized from a string. If this type of object is recognized, the library will switch to perform a multipart upload, passing along both the parameters as well as the multipart data. The class also offers a convenient constructor to initialize using an NSURL object pointing to the file, which in this case the name and filename parameters are extracted from the file itself.

Download

Here is an example on how you can perform a download:

var http = Http()

http.download("http://server.com/filename.txt",
    progress: { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)  in
        println("bytesWritten: \(bytesWritten), totalBytesWritten: \(totalBytesWritten), totalBytesExpectedToWrite: \(totalBytesExpectedToWrite)")
    }, completionHandler: { (response, error) in
        // handle response
})

By default the library uses the Applications 'Documents' directory to store the files received. If you want to store the file in a different directory add the 'destinationDirectory' parameter when calling the method, passing along the path you would like to use.

HTTP Basic/Digest authentication support

The library also leverages the build-in foundation support for http/digest authentication and exposes a convenient interface by allowing the credential object to be passed on the request. Here is an example:

It is advised that HTTPS should be used when performing authentication of this type
let credential = NSURLCredential(user: "john", password: "pass", persistence: .None)

http.GET("/protected/endpoint", credential: credential, completionHandler: {(response, error) in
   // handle response
})

You can also set a credential per protection space, so it’s automatically picked up once http challenge is requested by the server, thus omitting the need to pass the credential on each request. In this case, you must initialize the Http object with a custom session configuration object, that has its credentials storage initialized with your credentials:

// create a protection space
var protectionSpace: NSURLProtectionSpace = NSURLProtectionSpace(host: "httpbin.org", port: 443,`protocol`: NSURLProtectionSpaceHTTPS, realm: "me@kennethreitz.com", authenticationMethod: NSURLAuthenticationMethodHTTPDigest);

// setup credential
// notice that we use '.ForSession' type otherwise credential storage will discard and
// won't save it when doing 'credentialStorage.setDefaultCredential' later on
let credential = NSURLCredential(user: user, password: password, persistence: .ForSession)

// assign it to credential storage
var credentialStorage: NSURLCredentialStorage = NSURLCredentialStorage.sharedCredentialStorage()
credentialStorage.setDefaultCredential(credential, forProtectionSpace: protectionSpace);

// set up default configuration and assign credential storage
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.URLCredentialStorage = credentialStorage

// assign custom configuration to Http
var http = Http(baseURL: "http://httpbin.org", sessionConfig: configuration)

http.GET("/protected/endpoint", completionHandler: {(response, error) in
   // handle response
})

Hope you will find our library useful. Head over to our Cookbook examples for more example usages of the API and give us feedback on the mailing list. We will love to hear your thoughts and suggestions!

redhatlogo-wite