Working with swift 2.0 Xcode 7 and Alamofire 2.0, I would like to know how can I update the code with the correct HTTPAdditionalHeaders usage, before the update to 2.0, this manager session configuration worked perfectly but now the API gives me a BAD REQUEST due to an undefined headers. ¿How can I solve it? ¿is it possible to maintain the alamoFireManager session configuration HTTPAdditionalHeaders in the ApiClient?
ApiClient.swift
class ApiClient {
// User token
var oAuthToken = "R0Fh65G4MjCcD18OsiTcPIfHxohFIzFhapuWNFSBhX2conQ1e+3vlv0XrJQVcw7fRg=="
var mainService: MainService
init() {
let alamoFireManager = Manager.sharedInstance
alamoFireManager.session.configuration.HTTPAdditionalHeaders = [
"Authorization": "Bearer \(oAuthToken)"
]
// override the default challenge behavior in Alamofire using the SessionDelegate override closures.
//an example of how you can allow Alamofire to accept invalid certificates:
alamoFireManager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
credential = alamoFireManager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
if credential != nil {
disposition = .UseCredential
}
}
}
return (disposition, credential)
}
mainService = MainService()
}
}
MainService.swift
struct MainService {
enum Router: URLRequestConvertible {
static let baseURLString = "https://api.test.com/v1"
case GetList([String: AnyObject])
case GetById(String)
var method: Alamofire.Method {
switch self {
case .GetList:
return .GET
case .GetById:
return .GET
case .Add:
return .POST
case .Update:
return .PUT
case .Delete:
return .DELETE
}
}
var path: String {
switch self {
case .GetList:
return "/flyers"
case .GetById(let id):
return "/flyers/\(id)"
case .Add:
return "/flyers"
case .Update(let id, _):
return "/flyers/\(id)"
case .Delete(let id):
return "/flyers/\(id)"
}
}
var URLRequest: NSMutableURLRequest {
let URL = NSURL(string: Router.baseURLString)!
let mutableURLRequest = NSMutableURLRequest(URL: URL.URLByAppendingPathComponent(path))
mutableURLRequest.HTTPMethod = method.rawValue
switch self {
case .GetList(let parameters):
return Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: parameters).0
case .Add(let parameters):
return Alamofire.ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
case .Update(_, let parameters):
return Alamofire.ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
default:
return mutableURLRequest
}
}
}
func getList(completionHandler: ([Flyer]?, NSError?) -> ()) {
Alamofire.request(Router.GetList(["skip": Test().getSkip(), "total":Test().getTotal()])).responseJSON { (request, response, result) in
switch result {
case .Success(let data):
let json = JSON("Request success---------------------\(data)")
print(json)
case .Failure(_, let error):
print("Request failed with error: \(error)")
}
}
}
}
result
Request success---------------------{
code = "BAD_REQUEST";
message = "Bad request";
status = 400;
}
You MUST append Authorization
headers to the actual URL request. The way you are trying to modify the sharedInstance
configuration headers has never been supported by Apple. In iOS 9, they finally brought the behavior inline with the documentation. They flat out ignore headers set on the configuration after it has been applied to a URL session. Therefore, you either need to create your own custom URL session configuration and set the custom headers prior to creating the URL session, or in the event of an Authorization
header, you need to attach it directly to the request itself.
In your Router, you should attach the Authorization
header to your mutableURLRequest
before getting the list. This will solve your issue. You'll have to figure out how to refactor your logic to make the oAuthToken
accessible to the Router
. I would consider making it a static var oAuthToken
so you could easily access the value using APIClient.oAuthToken
.