URLSession and Synchronous HTTP request

It might sound stupid(and most of the time it is) but there are situations when you want to make a synchronous request using URLSession. I faced the situation when I had to log both request and response together.

Semaphores and Synchronous HTTP request

A asynchronous request looks something like this

func myRequest(){
    var request = URLRequest(url: URL(string: "your URL")!);
    request.httpMethod = "GET"
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        //get responce here
    }
    task.resume()
}

To make it behave we need to add semaphores. Semaphores are a signal person of multithreading world. They keep one side of traffic paused till the other side has completed its operation. Semaphores will work for us in two steps

  • Pause calling thread till Data task is ongoing
  • Give signal that data task is over now our calling thread can resume

Semaphore adaptation of our example above is given below

import UIKit
import Foundation

func myRequest(){
    var request = URLRequest(url: URL(string: "your URL")!);
    request.httpMethod = "GET"
    let semaphore: DispatchSemaphore = DispatchSemaphore(value: 0)
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        //get responce here
        //Use response
        print("2")
        semaphore.signal()
    }
    task.resume()
    print("1")
    semaphore.wait()
    print("3")
}

Caution while using semaphores

Semaphore use can make the calling thread pause. It won’t be very bright if we start using the above-given approach on the main thread. You will need to dispatch your calls as shown below at least.

DispatchQueue.global().async {
    myRequest()
}

Hope this helps someone in search of the synchronous HTTP request and is getting schooled about not using them instead of getting the solution.

A pat on the back !!