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.