Making an HTTP POST request

Since Apple's iTunes, APIs use GET requests to retrieve data. In this section, we will use the free http://httpbin.org service to show you how to make a POST request. The POST service that http://httpbin.org provides can be found at http://httpbin.org/post. This service will echo back the parameters that it receives so that we can verify that our request was made properly.

When we make a POST request, we generally have some data that we want to send or post to the server. This data takes the form of key/value pairs. These pairs are separated by an ampersand (&) symbol, and each key is separated from its value by an equals sign (=). As an example, let's say that we want to submit the following data to our service:

firstname: Jon
lastname: Hoffman
age: 47 years

The body of the POST request would take the following format:

firstname=Jon&lastname=Hoffman&age=47

Once we have the data in the proper format, we will then use the dataUsingEncoding() method, as we did with the GET request to properly encode the POST data.

Since the data going to the server is in the key/value format, the most appropriate way to store this data, prior to sending it to the service, is with a Dictionary object. With this in mind, we will need to create a method that will take a Dictionary object and return a string object that can be used for the POST request. The following code will do that:

func dictionaryToQueryString(dict: [String : String]) -> String {
  var parts = [String]()
  for (key, value) in dict {
    let part: String = key + "=" + value
    parts.append(part);
  }
  return parts.joinWithSeparator("&")
}

This function loops through each key/value pair of the Dictionary object and creates a String object that contains the key and the value separated by the equals sign (=). We then use the joinWithSeperator() function to join each item in the array, separated by the specified sting. In our case, we want to separate each string with the ampersand symbol (&). We then return this newly created string to the code that called it.

Now, let's create our sendPostRequest() function that will send the POST request to the http://httpbin.org post service. We will see a lot of similarities between this sendPostRequest() function and the sendGetRequest() function, which we showed you in the Making an HTTP GET request section of this chapter. Let's take a look at the following code:

public func sendPostRequest(handler: dataFromURLCompletionClosure) {
        
        let sessionConfiguration =
        NSURLSessionConfiguration.defaultSessionConfiguration()
        
        let urlString = "http://httpbin.org/post"
        if let encodeString =
            urlString.stringByAddingPercentEncodingWithAllowedCharacters(
                NSCharacterSet.URLQueryAllowedCharacterSet()),
            url = NSURL(string: encodeString) {
            
            let request = NSMutableURLRequest(URL:url)
            request.HTTPMethod = "POST"
            let params = dictionaryToQueryString(["One":"1 and 1", "Two":"2 and 2"])
            request.HTTPBody = params.dataUsingEncoding(
                NSUTF8StringEncoding, allowLossyConversion: true)
                
            let urlSession = NSURLSession(
                configuration:sessionConfiguration, delegate: nil, delegateQueue: nil)
            
            let sessionTask = urlSession.dataTaskWithRequest(request) {
                (data, response, error) in
                
                handler(response, data)
            }
            sessionTask.resume()
        }
    }

Now, let's walk though this code. Notice that we are using the same type alias, named DataFromURLCompletionClosure, that we used with the sendGetRequest() function. If you are not familiar with using a typealias object to define a closure type, please refer to Chapter 12, Working with Closures, for more information.

The sendPostRequest() function accepts one argument named handler, which is a closure that conforms to the DataFromURLCompletionClosure type. The handler closure will be used to process the data from the http://httpbin.org service once the service responds to our request.

Within our sendPostRequest() method, we start off by creating an instance of the NSURLSessionConfiguration class using the defaultSessionConfiguration() method, which creates a default session configuration instance. We are able to modify the session configuration properties after we create it, but, in this example, the default configuration is what we want.

After we created our session configuration, we create our URL string. This is the URL of the service we are connecting to. In this example, the URL is http://httpbin.org/post. Next, we run the URL string that we just created through the stringByAddingPercentEncodingWithAllowedCharacters() method to make sure our URL string is encoded properly. We use the URLQueryAllowedCharacterSet character set with this method to ensure we have a valid URL string.

Next, we use the URL string that we just built to create an instance of the NSURL class named url. Since this is a POST request, this NSURL instance will represent the location of the web service that we are connecting to.

We now create an instance of the NSMutableURLRequest class using the NSURL instance that we just created. We use the NSMutableURLRequest class, instead of the NSURLRequest class so that we can set the properties needed for our request. In this example, we set the HTTPMethod property; however, we can also set other properties such as the timeout interval or add items to our HTTP header.

Now, we use our dictionaryToQueryString() function, which we showed you at the beginning of this section, to build the data that we are going to post to the server. We use the dataUsingEncoding() function to make sure that our data is properly encoded prior to sending it to the server, and finally, the data is added to the HTTPBody property of the NSMutableURLRequest instance.

We use the sessionConfiguration variable (instance of the NSURLSessionConfiguration class) that we created at the beginning of the function to create an instance of the NSURLSession class. The NSURLSession class provides the API that we will use to connect to the post on http://httpbin.org post service. In this example, we use the dataTaskWithRequest() method of the NSURLSession instance to return an instance of the NSURLSessionDataTask class named sessionTask.

The sessionTask instance is what makes the request to the http://httpbin.org POST service. When we receive the response from the service, we use the handler callback to return both the NSURLResponse object and the NSData object. The NSURLResponse contains information about the response, and the NSData instance contains the body of the response.

Finally, we call the resume() method of the NSURLSessionDataTask instance to make the request to the web service. Remember, as we mentioned earlier, an NSURLSessionTask class will not send the request to the service until we call the resume() method.

We can then call the sendPostRequest() method in exactly the same way that we called the sendGetRequest() method.

When developing applications that communicate to other devices and services over the Internet, it is good practice to verify that we have a network connection. When developing mobile applications, it is also good practice to verify that we are not using a mobile connection (3G, 4G, and so on) to transfer large amounts of data.

Let's look at how to verify that we have a network connection and what type of connection we have.