title: Alamofire: How to Handle 401 Globally?
body: <p>I am trying to build a class which manages my network calls for my project. To this time, I mean handling errors globally, everything was fine. I created two functions; for post requests <code>postRequest(:_)</code> and for get requests <code>getRequests(:_)</code>. Datamaker functions to return data such as URL, parameters, headers etc, dataparser functions to parse response datas and finally a function to solve errors called <code>errorHandler()</code>. </p>
  
  <p>When I call the one of request function, I give a parameter to help function which request it should make. In the function it calls datamakers to get data firstly, then makes request with <code>Alamofire</code>, and at the end if the request was successful it calls dataparser and <code>onSuccess(data:)</code>closure or if it wasn't it calls <code>errorHandler(statusCode:)</code> and <code>onFailure(message:)</code> closure. </p>
  
  <p>I put a switch block in <code>errorHandler</code> and gave statusCode for its parameter. In <code>case 401</code> I called <code>Token().refresh()</code> and in it's completion called <code>errorHanlder</code>'s completion. In the <code>postRequest</code>/<code>errorHandler</code>'s completion block I called the <code>postRequest</code> again with the same parameters. It didn't work. I don't why, it went in infinite loop everytime and made requests consecutively. </p>
  
  <p>So I decided to try <a href="https://stackoverflow.com/users/1342462/cnoon">cnoon</a>'s <code>AuthorizationManager</code> class(can be found in this link; <a href="https://stackoverflow.com/questions/28733256/alamofire-how-to-handle-errors-globally">Alamofire : How to handle errors globally</a>). I changed it a little bit(added a new parameter as headers and changed <code>NetworkSuccessHandler</code>'s type to <code>NSData</code> ). Here is the new form: </p>
  
  <pre><code>public class AuthorizationManager: Manager {
      public typealias NetworkSuccessHandler = (NSData?) -&gt; Void
      public typealias NetworkFailureHandler = (NSHTTPURLResponse?, AnyObject?, NSError) -&gt; Void
  
      private typealias CachedTask = (NSHTTPURLResponse?, AnyObject?, NSError?) -&gt; Void
  
      private var cachedTasks = Array&lt;CachedTask&gt;()
      private var isRefreshing = false
  
      public func startRequest(
          method method: Alamofire.Method,
          URLString: URLStringConvertible,
          parameters: [String: AnyObject]?,
          encoding: ParameterEncoding,
          headers: [String:String]?,
          success: NetworkSuccessHandler?,
          failure: NetworkFailureHandler?) -&gt; Request?
          {
              let cachedTask: CachedTask = { [weak self] URLResponse, data, error in
                  guard let strongSelf = self else { return }
  
                  if let error = error {
                      failure?(URLResponse, data, error)
                  } else {
                      strongSelf.startRequest(
                          method: method,
                          URLString: URLString,
                          parameters: parameters,
                          encoding: encoding,
                          headers:  headers,
                          success: success,
                          failure: failure
                      )
                  }
              }
  
              if self.isRefreshing {
                  self.cachedTasks.append(cachedTask)
                  return nil
              }
  
              // Append your auth tokens here to your parameters
  
              let request = self.request(method, URLString, parameters: parameters, encoding: encoding, headers:  headers)
  
              request.response { [weak self] request, response, data, error in
                  guard let strongSelf = self else { return }
  
                  if let response = response where response.statusCode == 401 {
                      strongSelf.cachedTasks.append(cachedTask)
                      strongSelf.refreshTokens()
                      return
                  }
  
                  if let error = error {
                      failure?(response, data, error)
                  } else {
                      success?(data)
                  }
              }
  
              return request
      }
  
      func refreshTokens() {
          self.isRefreshing = true
  
              // Make the refresh call and run the following in the success closure to restart the cached tasks
          Token().refresh { () -&gt; () in
              let cachedTaskCopy = self.cachedTasks
              self.cachedTasks.removeAll()
              cachedTaskCopy.map { $0(nil, nil, nil) }
              self.isRefreshing = false
          }
      }
  }
  </code></pre>
  
  <p>Called it in my <code>postRequest</code> like:</p>
  
  <pre><code>func postRequest(requestType: postRequestType, additionalParameters: [String]?, onSuccess: onSuccessRequest = {_ in }, onFailure: onFailureRequest = {_ in }){
      print("post")
      let requestData = returnStaticDataForPostRequest(requestType, additionalParameters: additionalParameters)
      let Manager = AuthorizationManager()
      Manager.startRequest(method: .POST, URLString: requestData.0, parameters: requestData.2, encoding: requestData.3, headers: requestData.1, success: { (data) -&gt; Void in
          print("Manager")
          let json = JSON(data: data!)
          print(json)
          dataParserForPostRequests(json, parseForWhat: requestType)
          onSuccess(json: json)
          }) { (response, message, error) -&gt; Void in
              print(error)
      }
  
  }
  </code></pre>
  
  <p>And use of <code>postRequests</code> in the <code>ViewController</code>: </p>
  
  <pre><code>postRequest(.LOGIN, additionalParameters: ["asdasd", "asdasd"], onSuccess: { (json) -&gt; () in
              print("&gt;&gt;&gt;login_try_succeeded")        
              self.performSegueWithIdentifier("LoginToMain", sender: self)
              }) { (errorCode) -&gt; () in
              print("&gt;&gt;&gt;login_try_failed(\(errorCode))")
          }
  </code></pre>
  
  <p>This is the current state. When I run the code and try to login <code>AuthorizationManager</code> doesn't work. It just prints;</p>
  
  <pre><code>post
  </code></pre>
  
  <p>And lastly, I don't know if it's relevant but there is yellow warning at this line:</p>
  
  <pre><code>cachedTaskCopy.map { $0(nil, nil, nil) }
  </code></pre>
  
  <p>says <code>"Result of call to 'map' is unused"</code></p>
  
  <p>To sum up I need to figure out how I can handle 401's and I know how to use <code>AuthorizationManager</code> in a different way from this.</p>
  
  <p><strong>EDIT</strong>:</p>
  
  <p>I tried the run the this code directly from <code>ViewController</code> but it's not working at all. It's like code is invisible.</p>
  
  <pre><code>AuthorizationManager().startRequest(method: .POST, URLString: NSURL(string: "http://server.url/token")!, parameters: ["":""], encoding: .JSON,headers: ["":""], success: { (data) -&gt; Void in
              print(data)
              }) { (response, data, error) -&gt; Void in
                  print(error)
                  print("asdasd")
          }
  </code></pre>