GTRest

A lightweight Swift library for making web requests and consuming RESTful APIs!

Check it out on GitHub!

On this page

Making Requests

Make a web request by calling makeRequest(toURL:httpMethod:completion:) method. Provide the URL (URL object) and the HTTP method (a GTRest.HttpMethod value).

Completion handler returns a GTRest.Results object.

Example:

let url = URL(...) // A URL object.
let rest = GTRest()

rest.makeRequest(toURL: url, httpMethod: .get) { [unowned self] (results) in // or [weak self] (results) in
    // Handle results

    // Update your UI on main thread always:
    DispatchQueue.main.async {
        // Update UI.
    }
}

Request Results

Request results are represented by a GTRest.Results object. Completion handlers in makeRequest(toURL:withHttpMethod:completion:) and upload(files:toURL:withHttpMethod:completion:) methods return such an object.

let url = URL(...) // A URL object.
let rest = GTRest()

rest.makeRequest(toURL: url, httpMethod: .get) { [unowned self] (results) in // or [weak self] (results) in
    // Access data returned by the server:
    if let data = results.data {
        // Perform app-specific actions
    }

    // Access the response:
    if let response = results.response {
        // Do something with the response object if necessary.
        // Checking the HTTP status code :
        if (200...299).contains(response.httpStatusCode) {
            // Successful request.
        } else { ... }
    }

    // Access the error:
    if let error = results.error {
        // Do something with the error.
    }

    // Update your UI on main thread always:
    DispatchQueue.main.async {
        // Update UI.
    }
}

Request HTTP Headers

Use requestHttpHeaders property to set any required HTTP headers to the request.

Example:

var rest = GTRest()
rest.requestHttpHeaders.add(value: "application/json", forKey: "Content-Type")

Common request headers and MIME types are provided through the GTRest.HttpHeader and GTRest.MimeType custom types respectively.

rest.requestHttpHeaders.add(value: GTRest.MimeType.applicationJson.rawValue,
                            forKey: GTRest.HttpHeader.contentType.rawValue)

Multiple headers can be added as well:

let requestHeaders = ["Content-type": "application/json", "Authorization": "Bearer abc123"]
rest.requestHttpHeaders.add(multipleValues: requestHeaders)

URL Query and HTTP Body Parameters

Use urlQueryParameters property to set URL query parameters before making the request.

rest.urlQueryParameters.add(value: "gabriel", forKey: "username")
rest.urlQueryParameters.add(value: "37", forKey: "age")

// Result in the URL:
// https://yourURL?username=gabriel&age=37

Multiple values can be added at once here too:

let params = ["username": "gabriel", "age": "37"]
rest.urlQueryParameters.add(multipleValues: params)

In a similar fashion HTTP body parameters can be also set:

// Single parameter:
rest.httpBodyParameters.add(value: "gabriel", forKey: "username")

// Multiple parameters:
let params = ["username": "gabriel", "age": "37"]
rest.httpBodyParameters.add(multipleValues: params)

Important Note: Use httpBodyParameters property when application/json or application/x-www-form-urlencoded content type has been specified as a request HTTP header. For any other content type, assign the HTTP body data directly to the httpBody property.

Response HTTP Headers

Any response HTTP headers returned by the server can be accessed through the headers property of the GTRest.Response object in the GTRest.Results results.

headers is a GTRest.ResponseHeaders object.

rest.makeRequest(toURL: url, httpMethod: .get) { [unowned self] (results) in // or [weak self] (results) in
    // Access the response:
    if let response = results.response {
        // Access headers:
        let headers = response.headers
    }
}

File Uploading

Upload files using the upload(files:toURL:withHttpMethod:completion:) method.

A file is described by a GTRest.FileInfo object.

Important: multipart/form-data; boundary=xxx is the content type used for web requests made through this method. You do not have to provide it, it is automatically set.

Example:

var rest = GTRest()

// Prepare the files that will be uploaded.
var resume = GTRest.FileInfo()
resume.fileContents = ... // File contents data
resume.mimetype = "application/pdf" // or GTRest.MimeType.applicationPDF.rawValue
resume.filename = "resume.pdf"

var avatar = GTRest.FileInfo()
avatar.fileContents = ... // File contents data
avatar.mimetype = GTRest.MimeType.imagePNG.rawValue
avatar.filename = "avatar.png"

// Optionally, set any request HTTP methods, but not the "content-type".
// Also, set any required URL query or HTTP body parameters.

// Prepare the URL.
let url = ... // A URL object.

rest.upload(files: [resume, avatar], toURL: url, withHttpMethod: .post) { [unowned self] (results, failedFiles) in // or [unowned self] (results, failedFiles) in
    if let failedFiles = failedFiles {
        // Do something with the files that failed to be uploaded.
    }

    // Do something with the results.
    if let data = results.data {
        // ...
    }

    // Update your UI on main thread always:
    DispatchQueue.main.async {
        // Update UI.
    }
}

Fetching Single Data

Fetch single data with the getData(fromURL:completion:) method.

This method is useful for fetching single data from a URL, usually the contents of a file. For example, the image data for a user profile picture, or the contents of a PDF file.

Example:

let rest = GTRest()
rest.getData(fromURL: url)  { [unowned self] (data) in // or [weak self] (data) in
    if let data = data {
        // Do something with the fetched data.
    }
}

Converting Raw Data To Custom Types

GTRest.Results object returned when making requests provides a convenient method named convertData(toType:decoderConfiguration:). Its purpose is to convert raw fetched data from JSON (a Data object) into a custom type by decoding it using JSONDecoder.

It is required that custom type must conform to Decodable or Codable protocol.

JSONDecoder object used to decode data in that method can be configured in the decoderConfiguration handler. Keep it nil in case you don’t want to make any configuration to JSONDecoder instance.

In case decoding fails an exception is thrown by the method.

Example:

Consider the following struct:

struct User: Codable {
    var id: Int?
    var firstName: String?
    var lastName: String?
}

Also, the following data fetched from server:

{
    "id": 325,
    "first_name": "Gabriel",
    "last_name": "Theodoropoulos"
}

Here’s how to convert fetched user data, using the decoderConfiguration to set the convertFromSnakeCase as the keyDecodingStrategy:

let rest = GTRest()
let url = URL(...)
// Additional configuration...

rest.makeRequest(toURL: url, withHttpMethod: .get) { (results) in
    do {
        if let user = try results.convertData(toType: User.self, decoderConfiguration: { (decoder) in
            decoder.keyDecodingStrategy = .convertFromSnakeCase
        }) {
            // User data has been successfully converted into a `User` object.
            print(user)
        }
    } catch {
        print(error.localizedDescription)
    }
}

Additional Notes

  • requestHttpHeaders, urlQueryParameters, httpBodyParameters and headers property in GTRest.Response type are objects of the GTRest.RestEntity custom type. It adopts the GTKeyValueManageable protocol which makes the following methods available:
    • add(value:forKey:)
    • add(multipleValues:)
    • value(forKey:)
    • getStorageValues()
    • totalItems()
  • All web requests are performed asynchronously in background threads.
  • Optionally use GTRest.HttpHeader and GTRest.MimeType custom types for common request header and MIME type values.

Created by Gabriel Theodoropoulos