- iPhone iOS 8+ app
- utente collegato sarà caricare una foto del profilo
L'applicazione utilizza già Alamofire per effettuare richieste firmate alle API di back-end. Davvero semplice: l'app invia tre intestazioni HTTP specifiche (Authorization
, X-Api-Key
e timestamp
) per la richiesta di essere firmata. Chiamando Alamofire.request
è facile inviare headers
come parametro, quindi funziona perfettamente.
Ora gli utenti devono essere in grado di caricare l'immagine del profilo. Dal momento che l'utente è già connesso all'app, l'API di backend saprà quale utente sta inviando l'immagine tramite la sua richiesta firmata - e questa è la parte difficile con cui ho dovuto lottare nelle ultime ore. Alamofire.upload
accetta parametri completamente diversi da .request
, quindi non riesco a capire come inviare le intestazioni quando si carica un file.
Provato il vecchio Alamofire.Manager.session.configuration.HTTPAdditionalHeaders
, ma è no longer supported. Trovato tonnellate di esempi di codice per il caricamento di file, nessuno considera l'invio di intestazioni personalizzate.
Come posso inviare intestazioni personalizzate quando si utilizza il metodo Alamofire.upload
?
typealias requestDataType = [String:AnyObject]
private func signRequest(data: requestDataType) -> [String:String] {
var headers = [String:String]()
var authString = ""
var signatureHeaders = ""
// Iterates over SORTED data dictionary to build headers
for (k,v) in (data.sort{$0.0 < $1.0}) {
if !authString.isEmpty {
authString += "\n"
signatureHeaders += " "
}
authString += "\(k): \(v)"
signatureHeaders += "\(k)"
headers[k] = "\(v)"
}
let userApiKey = _loggedInUser!["api_key"].string!
let signature = authString.sha256(_loggedInUser!["api_secret"].string!)
headers["X-Api-Key"] = userApiKey
headers["Authorization"] = "Signature headers=\"\(signatureHeaders)\",keyId=\"\(userApiKey)\",algorithm=\"hmac-sha256\",signature=\"\(signature)\""
return headers
}
func uploadProfilePicture(photo: UIImage, callback: apiCallback){
guard let userId = _loggedInUser?["pk"].int else {
callback(Response(success: false, responseMessage: "User not logged in"))
return
}
let requestData: requestDataType = ["timestamp": "\(Int(NSDate().timeIntervalSince1970))"]
let aManager = Manager.sharedInstance
print(self.signRequest(requestData)) // Prints correct headers (Authorization, X-Api-Key, timestamp)
aManager.session.configuration.HTTPAdditionalHeaders = self.signRequest(requestData)
print(aManager.session.configuration.HTTPAdditionalHeaders) // Prints default headers, completely ignoring my custom headers
aManager.upload(.POST, "\(_apiBaseUrl)profiles/\(userId)/photo/", multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(photo, 0.8) {
multipartFormData.appendBodyPart(data: imageData, name: "upload", fileName: "userphoto.jpg", mimeType: "image/jpeg")
}
for (key, value) in requestData {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
}, encodingCompletion: {
encodingResult in
debugPrint(encodingResult)
})
}
Le richieste sono passate. Nel registro backend posso vedere la richiesta restituita HTTP 403
- Non autorizzato in quanto non è stato possibile firmare la richiesta. Stampando le intestazioni delle richieste, non sono state ricevute intestazioni di autenticazione personalizzate dal server.
Aggiungere almeno il prototipo per il metodo 'signRequest' –
@DavidBerry aggiornato. – mathielo